mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
e4b11ab109
git-svn-id: https://svn.fhem.de/fhem/trunk@25306 2b470e98-0d58-463d-a4d8-8e2adae1ed80
3407 lines
109 KiB
Perl
3407 lines
109 KiB
Perl
####################################################################################################
|
|
#
|
|
# 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 <kontakt@it-buchinger.de> 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$
|
|
#
|
|
####################################################################################################
|
|
# 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',
|
|
'experimental::smartmatch';
|
|
|
|
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)
|
|
);
|
|
}
|
|
|
|
#-- 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 <name> UWZ <CountryCode> <PLZ> <Interval> "
|
|
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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$URL_language = 'de';
|
|
}
|
|
if ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$URL_language = 'nl';
|
|
}
|
|
if ( $hash->{CountryCode} ~~ ['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 );
|
|
|
|
given ($cmd) {
|
|
when ("?") {
|
|
return $usage;
|
|
}
|
|
|
|
when ('update') {
|
|
Log $hash, 4, 'set command: ' . $cmd;
|
|
$hash->{fhem}{LOCAL} = 1;
|
|
Start($hash);
|
|
$hash->{fhem}{LOCAL} = 0;
|
|
}
|
|
|
|
default {
|
|
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 ( $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} ~~ ['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} ~~ ['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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$URL_language = 'de';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$URL_language = 'nl';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] );
|
|
$newState = 'Aantal waarschuwingen: ' . $values{WarnCount}
|
|
if ( $hash->{CountryCode} ~~ ['NL'] );
|
|
$newState = 'Avertissements: ' . $values{WarnCount}
|
|
if ( $hash->{CountryCode} ~~ ['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 ( $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} ~~ ['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} ~~ ['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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$uclang = 'DE';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$uclang = 'NL';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
|
|
$hagelcount = my @hagelmatch =
|
|
$single_warning->{'payload'}{'translationsLongText'}{'DE'} =~
|
|
/Hagel/g;
|
|
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
|
|
$hagelcount = my @hagelmatch =
|
|
$single_warning->{'payload'}{'translationsLongText'}{'NL'} =~
|
|
/hagel/g;
|
|
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['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 ( $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} ~~ ['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} ~~ ['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 .= '<table><tr><td>';
|
|
$ret .=
|
|
'<table class="block" '
|
|
. $attr
|
|
. '><tr><th class="'
|
|
. $htmltitleclass
|
|
. '" colspan="2">'
|
|
. $htmltitle
|
|
. '</th></tr>';
|
|
|
|
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 .= '</table>';
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
|
|
}
|
|
else {
|
|
|
|
$ret .= '<table><tr><td>';
|
|
$ret .=
|
|
'<table class="block wide" width="600px"><tr><th class="'
|
|
. $htmltitleclass
|
|
. '" colspan="2">'
|
|
. $htmltitle
|
|
. '</th></tr>';
|
|
$ret .= '<tr><td class="uwzIcon" style="vertical-align:top;">';
|
|
|
|
# language by AttrVal
|
|
if ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$ret .= '<b>Keine Warnungen</b>';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$ret .= '<b>Geen waarschuwingen</b>';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['FR'] ) {
|
|
$ret .= '<b>Aucune alerte</b>';
|
|
}
|
|
else {
|
|
$ret .= '<b>No Warnings</b>';
|
|
}
|
|
|
|
# end language by AttrVal
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
}
|
|
|
|
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 .= '<table><tr><td>';
|
|
$ret .=
|
|
'<table class="block" '
|
|
. $attr
|
|
. '><tr><th class="'
|
|
. $htmltitleclass
|
|
. '" colspan="2">'
|
|
. $htmltitle
|
|
. '</th></tr>';
|
|
|
|
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 .= '</table>';
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
|
|
}
|
|
else {
|
|
|
|
$ret .= '<table><tr><td>';
|
|
$ret .=
|
|
'<table class="block wide" width="600px"><tr><th class="'
|
|
. $htmltitleclass
|
|
. '" colspan="2">'
|
|
. $htmltitle
|
|
. '</th></tr>';
|
|
$ret .= '<tr><td class="uwzIcon" style="vertical-align:top;">';
|
|
|
|
# language by AttrVal
|
|
if ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$ret .= '<b>Keine Warnungen</b>';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$ret .= '<b>Geen waarschuwingen</b>';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['FR'] ) {
|
|
$ret .= '<b>Aucune alerte</b>';
|
|
}
|
|
else {
|
|
$ret .= '<b>No Warnings</b>';
|
|
}
|
|
|
|
# end language by AttrVal
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
$ret .= '</td></tr>';
|
|
$ret .= '</table>';
|
|
}
|
|
|
|
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 .=
|
|
'<table class="uwz-fp" style="width:'
|
|
. $tablewidth
|
|
. 'px"><tr><th class="'
|
|
. $htmltitleclass
|
|
. '" colspan="'
|
|
. ReadingsVal( $name, 'WarnCount', 'none' ) . '">'
|
|
. $htmltitle
|
|
. '</th></tr>';
|
|
$ret .= '<tr>';
|
|
|
|
if ( $htmlsequence eq 'descending' ) {
|
|
for (
|
|
my $i = ReadingsVal( $name, 'WarnCount', '' ) - 1 ;
|
|
$i >= 0 ;
|
|
$i--
|
|
)
|
|
{
|
|
$ret .=
|
|
'<td class="uwzIcon"><img width="80px" src="'
|
|
. ReadingsVal( $name, 'Warn_' . $i . '_IconURL', '' )
|
|
. '"></td>';
|
|
}
|
|
}
|
|
else {
|
|
for ( my $i = 0 ; $i < ReadingsVal( $name, 'WarnCount', '' ) ; $i++ ) {
|
|
$ret .=
|
|
'<td class="uwzIcon"><img width="80px" src="'
|
|
. ReadingsVal( $name, 'Warn_' . $i . '_IconURL', '' )
|
|
. '"></td>';
|
|
}
|
|
}
|
|
$ret .= '</tr>';
|
|
$ret .= '</table>';
|
|
|
|
return $ret;
|
|
}
|
|
|
|
#####################################
|
|
sub UWZAsHtmlMovie {
|
|
my $name = shift;
|
|
my $land = shift;
|
|
|
|
my $url = Map2Movie($land);
|
|
my $hash = $defs{$name};
|
|
|
|
my $ret = '<table><tr><td>';
|
|
|
|
$ret .= '<table class="block wide">';
|
|
$ret .= '<tr class="even"><td>';
|
|
|
|
if ( defined($url) ) {
|
|
$ret .= '<video controls="controls">';
|
|
$ret .= '<source src="' . $url . '" type="video/mp4">';
|
|
$ret .= '</video>';
|
|
|
|
}
|
|
else {
|
|
# language by AttrVal
|
|
if ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$ret .= 'unbekannte Landbezeichnung';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$ret .= 'Onbekende landcode';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['FR'] ) {
|
|
$ret .= 'code de pays inconnu';
|
|
}
|
|
else {
|
|
$ret .= 'unknown movie setting';
|
|
}
|
|
|
|
# end language by AttrVal
|
|
}
|
|
|
|
$ret .= '</td></tr></table></td></tr>';
|
|
$ret .= '</table>';
|
|
|
|
return $ret;
|
|
}
|
|
|
|
#####################################
|
|
sub UWZAsHtmlKarteLand {
|
|
my $name = shift;
|
|
my $land = shift;
|
|
|
|
my $url = Map2Image($land);
|
|
my $hash = $defs{$name};
|
|
|
|
my $ret = '<table><tr><td>';
|
|
|
|
$ret .= '<table class="block wide">';
|
|
$ret .= '<tr class="even"><td>';
|
|
|
|
if ( defined($url) ) {
|
|
$ret .= '<img src="' . $url . '">';
|
|
|
|
}
|
|
else {
|
|
# language by AttrVal
|
|
if ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$ret .= 'unbekannte Landbezeichnung';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$ret .= 'onbekende landcode';
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['FR'] ) {
|
|
$ret .= 'code de pays inconnu';
|
|
}
|
|
else {
|
|
$ret .= 'unknown map setting';
|
|
}
|
|
|
|
# end language by AttrVal
|
|
}
|
|
|
|
$ret .= '</td></tr></table></td></tr>';
|
|
$ret .= '</table>';
|
|
|
|
return $ret;
|
|
}
|
|
|
|
#####################################
|
|
sub UWZHtmlFrame {
|
|
my ( $hash, $readingStart, $attr, $parm ) = @_;
|
|
|
|
my $ret = '';
|
|
my $name = $hash->{NAME};
|
|
$ret .=
|
|
'<tr><td class="uwzIcon" style="vertical-align:top;"><img src="'
|
|
. ReadingsVal( $name, $readingStart . '_IconURL', '' )
|
|
. '"></td>';
|
|
$ret .=
|
|
'<td class="uwzValue"><b>'
|
|
. ReadingsVal( $name, $readingStart . '_ShortText', '' )
|
|
. '</b><br><br>';
|
|
$ret .= ReadingsVal( $name, $readingStart . '_LongText', '' ) . '<br><br>'
|
|
if ($parm);
|
|
|
|
$ret .= UWZHtmlTimestamp( $hash, $readingStart . '_Start', $attr );
|
|
$ret .= UWZHtmlTimestamp( $hash, $readingStart . '_End', $attr );
|
|
$ret .= '</tr></table>';
|
|
$ret .= '</td></tr>';
|
|
|
|
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 .= '<table ' . $attr . '><tr><th></th><th></th></tr><tr>';
|
|
}
|
|
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 ( $hash->{CountryCode} ~~ [ 'DE', 'AT', 'CH' ] ) {
|
|
$ret .=
|
|
"<td><b>$DEText[$StartEnd]</b></td><td>"
|
|
. "$DEweekdays[$wday], $mday $DEmonths[$mon] "
|
|
. ( 1900 + $year )
|
|
. " $hour:$min "
|
|
. "$DEText[2]</td>";
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['NL'] ) {
|
|
$ret .=
|
|
"<td><b>$NLText[$StartEnd]</b></td><td>"
|
|
. "$NLweekdays[$wday], $mday $NLmonths[$mon] "
|
|
. ( 1900 + $year )
|
|
. " $hour:$min "
|
|
. "$NLText[2]</td>";
|
|
}
|
|
elsif ( $hash->{CountryCode} ~~ ['FR'] ) {
|
|
$ret .=
|
|
"<td><b>$FRText[$StartEnd]</b></td><td>"
|
|
. "$FRweekdays[$wday], $mday $FRmonths[$mon] "
|
|
. ( 1900 + $year )
|
|
. " $hour:$min "
|
|
. "$FRText[2]</td>";
|
|
}
|
|
else {
|
|
$ret .=
|
|
"<td><b>$ENText[$StartEnd]</b></td><td>"
|
|
. "$ENweekdays[$wday], $mday $ENmonths[$mon] "
|
|
. ( 1900 + $year )
|
|
. " $hour:$min "
|
|
. "$ENText[2]</td>";
|
|
}
|
|
|
|
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 = '<html><table><tr><td>';
|
|
|
|
$ret .= '<table class="block wide">';
|
|
|
|
$ret .= '<tr class="even">';
|
|
$ret .= '<td><b>city</b></td>';
|
|
$ret .= '<td><b>country</b></td>';
|
|
$ret .= '<td><b>latitude</b></td>';
|
|
$ret .= '<td><b>longitude</b></td>';
|
|
$ret .= '</tr>';
|
|
|
|
foreach my $locres ( $search->{cities}->{city} ) {
|
|
my $linecount = 1;
|
|
while ( my ( $key, $value ) = each(%$locres) ) {
|
|
if ( $linecount % 2 == 0 ) {
|
|
$ret .= '<tr class="even">';
|
|
}
|
|
else {
|
|
$ret .= '<tr class="odd">';
|
|
}
|
|
$ret .= '<td>' . encode( 'utf-8', $value->{'name'} ) . '</td>';
|
|
$ret .= '<td>' . $value->{'country-name'} . '</td>';
|
|
$ret .= '<td>' . $value->{'latitude'} . '</td>';
|
|
$ret .= '<td>' . $value->{'longitude'} . '</td>';
|
|
|
|
my $aHref =
|
|
'<a href="/fhem?cmd=get%20'
|
|
. $name
|
|
. '%20AreaID%20'
|
|
. $value->{'latitude'}
|
|
. ','
|
|
. $value->{'longitude'}
|
|
. $::FW_CSRF
|
|
. '">Get AreaID</a>';
|
|
|
|
$ret .= '<td>' . $aHref . '</td>';
|
|
$ret .= '</tr>';
|
|
$linecount++;
|
|
}
|
|
}
|
|
|
|
$ret .= '</table></td></tr>';
|
|
$ret .= '</table></html>';
|
|
|
|
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 =
|
|
'<html>Please use the following statement to define Unwetterzentrale for your location:<br /><br />';
|
|
$ret .= '<table width=100%><tr><td>';
|
|
$ret .= '<table class="block wide">';
|
|
$ret .= '<tr class="even">';
|
|
$ret .=
|
|
"<td height=100><center><b>define Unwetterzentrale UWZ $CC $AreaID 3600</b></center></td>";
|
|
$ret .= '</tr>';
|
|
$ret .= '</table>';
|
|
$ret .= '</td></tr></table>';
|
|
|
|
$ret .= '<br />';
|
|
$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:<br />';
|
|
|
|
$ret .= '<table width=100%><tr><td>';
|
|
$ret .= '<table class="block wide">';
|
|
$ret .= '<tr class="even">';
|
|
$ret .=
|
|
"<td height=100><center>define UWZ_Map_Europe weblink htmlCode { UWZAsHtmlKarteLand('Unwetterzentrale','europa') }</center></td>";
|
|
$ret .= '</tr>';
|
|
$ret .= '</table>';
|
|
$ret .= '</td></tr></table>';
|
|
|
|
$ret .= '</html>';
|
|
|
|
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
|
|
|
|
<a name="UWZ"></a>
|
|
<h3>UWZ</h3>
|
|
<ul>
|
|
<a name="UWZdefine"></a>
|
|
This modul extracts thunderstorm warnings from <a href="https://www.unwetterzentrale.de">www.unwetterzentrale.de</a>.
|
|
<br/>
|
|
Therefore the same interface is used as the Android App <a href="https://www.alertspro.com">Alerts Pro</a> 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.
|
|
<br>
|
|
<i>The following Perl-Modules are used within this module: HTTP::Request, LWP::UserAgent, JSON, Encode::Guess und HTML::Parse</i>.
|
|
<br/><br/>
|
|
<b>Define</b>
|
|
<ul>
|
|
<br>
|
|
<code>define <Name> UWZ [CountryCode] [AreaID] [INTERVAL]</code>
|
|
<br><br><br>
|
|
Example:
|
|
<br>
|
|
<code>
|
|
define Unwetterzentrale UWZ UK 08357 1800<br>
|
|
attr Unwetterzentrale download 1<br>
|
|
attr Unwetterzentrale humanreadable 1<br>
|
|
attr Unwetterzentrale maps eastofengland unitedkingdom<br><br>
|
|
define UnwetterDetails weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}<br>
|
|
define UnwetterMapE_UK weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","eastofengland")}<br>
|
|
define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")}
|
|
define UnwetterMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","clouds-precipitation-uk")}
|
|
</code>
|
|
<br>
|
|
|
|
<li><code>[CountryCode]</code>
|
|
<br>
|
|
Possible values: DE, AT, CH, UK, ...<br/>
|
|
(for other countries than germany use SEARCH for CountryCode to start device in search mode)
|
|
</li><br>
|
|
<li><code>[AreaID]</code>
|
|
<br>
|
|
For Germany you can use the postalcode, other countries use SEARCH for CountryCode to start device in search mode.
|
|
<br>
|
|
</li><br>
|
|
<li><code>[INTERVAL]</code>
|
|
<br>
|
|
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.
|
|
<br>
|
|
</li><br>
|
|
|
|
<br><br><br>
|
|
Example Search-Mode:
|
|
<br>
|
|
<code>
|
|
define Unwetterzentrale UWZ SEARCH<br>
|
|
</code>
|
|
<br>
|
|
now get the AreaID for your location (example shows london):
|
|
<br>
|
|
<code>
|
|
get Unwetterzentrale SearchAreaID London<br>
|
|
</code>
|
|
<br>
|
|
now redefine your device with the outputted CountryCode and AreaID.
|
|
<br>
|
|
|
|
<br>
|
|
|
|
|
|
</ul>
|
|
<br>
|
|
|
|
<a name="UWZget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>get <name> soil-frost</code>
|
|
<br>
|
|
give info about current soil frost (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> extremfrost</code>
|
|
<br>
|
|
give info about current frost (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> thunderstorm</code>
|
|
<br>
|
|
give info about current thunderstorm (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> glaze</code>
|
|
<br>
|
|
give info about current glaze (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> glazed-rain</code>
|
|
<br>
|
|
give info about current freezing rain (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> hail</code>
|
|
<br>
|
|
give info about current hail (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> heat</code>
|
|
<br>
|
|
give info about current heat (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> rain</code>
|
|
<br>
|
|
give info about current rain (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> snow</code>
|
|
<br>
|
|
give info about current snow (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> storm</code>
|
|
<br>
|
|
give info about current storm (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> forest-fire</code>
|
|
<br>
|
|
give info about current forest fire (active|inactive).
|
|
</li><br>
|
|
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
<b>Get (Search-Mode)</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>get <name> SearchAreaID <city></code>
|
|
<br>
|
|
Get AreaID coresponnding to entered location.
|
|
</li><br>
|
|
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
|
|
|
|
<a name="UWZset"></a>
|
|
<b>Set</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>set <name> update</code>
|
|
<br>
|
|
Executes an imediate update of thunderstorm warnings.
|
|
</li><br>
|
|
</ul>
|
|
|
|
<br>
|
|
<a name="UWZattr"></a>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>download</code>
|
|
<br>
|
|
Download maps during update (0|1).
|
|
<br>
|
|
</li>
|
|
<li><code>savepath</code>
|
|
<br>
|
|
Define where to store the map png files (default: /tmp/).
|
|
<br>
|
|
</li>
|
|
<li><code>maps</code>
|
|
<br>
|
|
Define the maps to download space seperated. For possible values see <code>UWZAsHtmlKarteLand</code>.
|
|
<br>
|
|
</li>
|
|
<li><code>humanreadable</code>
|
|
<br>
|
|
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).
|
|
<br>
|
|
</li>
|
|
<li><code>lang</code>
|
|
<br>
|
|
Overwrite requested language for short and long warn text. (de|en|it|fr|es|..).
|
|
<br>
|
|
</li>
|
|
<li><code>sort_readings_by</code>
|
|
<br>
|
|
define how readings will be sortet (start|severity|creation).
|
|
<br>
|
|
</li>
|
|
<li><code>htmlsequence</code>
|
|
<br>
|
|
define warn order of html output (ascending|descending).
|
|
<br>
|
|
</li>
|
|
<li><code>htmltitle</code>
|
|
<br>
|
|
title / header for the html ouput
|
|
<br>
|
|
</li>
|
|
<li><code>htmltitleclass</code>
|
|
<br>
|
|
css-Class of title / header for the html ouput
|
|
<br>
|
|
</li>
|
|
<li><code>localiconbase</code>
|
|
<br>
|
|
define baseurl to host your own thunderstorm warn pics (filetype is png).
|
|
<br>
|
|
</li>
|
|
<li><code>intervalAtWarnLevel</code>
|
|
<br>
|
|
define the interval per warnLevel. Example: 2=1800,3=900,4=300
|
|
<br>
|
|
</li>
|
|
|
|
|
|
|
|
<br>
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
<a name="UWZreading"></a>
|
|
<b>Readings</b>
|
|
<ul>
|
|
<br>
|
|
<li><b>Warn_</b><i>0|1|2|3...|9</i><b>_...</b> - active warnings</li>
|
|
<li><b>WarnCount</b> - warnings count</li>
|
|
<li><b>WarnUWZLevel</b> - total warn level </li>
|
|
<li><b>WarnUWZLevel_Color</b> - total warn level color</li>
|
|
<li><b>WarnUWZLevel_Str</b> - total warn level string</li>
|
|
<li><b>Warn_</b><i>0</i><b>_AltitudeMin</b> - minimum altitude for warning </li>
|
|
<li><b>Warn_</b><i>0</i><b>_AltitudeMax</b> - maximum altitude for warning </li>
|
|
<li><b>Warn_</b><i>0</i><b>_EventID</b> - warning EventID </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation</b> - warning creation </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation_Date</b> - warning creation datum </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation_Time</b> - warning creation time </li>
|
|
<li><b>currentIntervalMode</b> - default/warn, Interval is read from INTERVAL or INTERVALWARN Internal</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start</b> - begin of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start_Date</b> - start date of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start_Time</b> - start time of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End</b> - end of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End_Date</b> - end date of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End_Time</b> - end time of warnperiod</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Severity</b> - Severity of thunderstorm (0 no thunderstorm, 4, 7, 11, .. heavy thunderstorm)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Hail</b> - warning contains hail</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Type</b> - kind of thunderstorm</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Type_Str</b> - kind of thunderstorm (text)</li>
|
|
<ul>
|
|
<li><b>1</b> - unknown</li>
|
|
<li><b>2</b> - storm</li>
|
|
<li><b>3</b> - snow</li>
|
|
<li><b>4</b> - rain</li>
|
|
<li><b>5</b> - frost</li>
|
|
<li><b>6</b> - forest fire</li>
|
|
<li><b>7</b> - thunderstorm</li>
|
|
<li><b>8</b> - glaze</li>
|
|
<li><b>9</b> - heat</li>
|
|
<li><b>10</b> - freezing rain</li>
|
|
<li><b>11</b> - soil frost</li>
|
|
</ul>
|
|
<li><b>Warn_</b><i>0</i><b>_uwzLevel</b> - Severity of thunderstorm (0-5)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_uwzLevel_Str</b> - Severity of thunderstorm (text)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_levelName</b> - Level Warn Name</li>
|
|
<li><b>Warn_</b><i>0</i><b>_ShortText</b> - short warn text</li>
|
|
<li><b>Warn_</b><i>0</i><b>_LongText</b> - detailed warn text</li>
|
|
<li><b>Warn_</b><i>0</i><b>_IconURL</b> - cumulated URL to display warn-icons from <a href="https://www.unwetterzentrale.de">www.unwetterzentrale.de</a></li>
|
|
</ul>
|
|
<br>
|
|
|
|
<a name="UWZweblinks"></a>
|
|
<b>Weblinks</b>
|
|
<ul>
|
|
<br>
|
|
|
|
With the additional implemented functions <code>UWZAsHtml, UWZAsHtmlLite, UWZAsHtmlFP, UWZAsHtmlKarteLand and UWZAsHtmlMovie</code> HTML-Code will be created to display warnings and weathermovies, using weblinks.
|
|
<br><br><br>
|
|
Example:
|
|
<br>
|
|
<li><code>define UnwetterDetailiert weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterFloorplan weblink htmlCode {FHEM::UWZ::UWZAsHtmlFP("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterKarteLand weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","Bayern")}</code></li>
|
|
<ul>
|
|
<li>The second parameter should be one of:
|
|
<ul>
|
|
<li>europa</li>
|
|
<br/>
|
|
<li>deutschland</li>
|
|
<li>deutschland-small</li>
|
|
<li>niedersachsen</li>
|
|
<li>bremen</li>
|
|
<li>bayern</li>
|
|
<li>schleswig-holstein</li>
|
|
<li>hamburg</li>
|
|
<li>mecklenburg-vorpommern</li>
|
|
<li>sachsen</li>
|
|
<li>sachsen-anhalt</li>
|
|
<li>nordrhein-westfalen</li>
|
|
<li>thueringen</li>
|
|
<li>rheinland-pfalz</li>
|
|
<li>saarland</li>
|
|
<li>baden-wuerttemberg</li>
|
|
<li>hessen</li>
|
|
<li>brandenburg</li>
|
|
<li>berlin</li>
|
|
<br/>
|
|
<li>oesterreich</li>
|
|
<li>burgenland</li>
|
|
<li>kaernten</li>
|
|
<li>niederoesterreich</li>
|
|
<li>oberoesterreich</li>
|
|
<li>salzburg</li>
|
|
<li>steiermark</li>
|
|
<li>tirol</li>
|
|
<li>vorarlberg</li>
|
|
<li>wien</li>
|
|
<br/>
|
|
<li>schweiz</li>
|
|
<li>aargau</li>
|
|
<li>appenzell_ausserrhoden</li>
|
|
<li>appenzell_innerrhoden</li>
|
|
<li>basel_landschaft</li>
|
|
<li>basel_stadt</li>
|
|
<li>bern</li>
|
|
<li>fribourg</li>
|
|
<li>geneve</li>
|
|
<li>glarus</li>
|
|
<li>graubuenden</li>
|
|
<li>jura</li>
|
|
<li>luzern</li>
|
|
<li>neuchatel</li>
|
|
<li>nidwalden</li>
|
|
<li>obwalden</li>
|
|
<li>schaffhausen</li>
|
|
<li>schwyz</li>
|
|
<li>solothurn</li>
|
|
<li>stgallen</li>
|
|
<li>ticino</li>
|
|
<li>thurgau</li>
|
|
<li>uri</li>
|
|
<li>waadt</li>
|
|
<li>wallis</li>
|
|
<li>zug</li>
|
|
<li>zuerich</li>
|
|
<br/>
|
|
<li>liechtenstein</li>
|
|
<br/>
|
|
<li>belgique</li>
|
|
<br/>
|
|
<li>denmark</li>
|
|
<br/>
|
|
<li>finnland</li>
|
|
<br/>
|
|
<li>france</li>
|
|
<li>alsace</li>
|
|
<li>aquitaine</li>
|
|
<li>basse-normandie</li>
|
|
<li>bretagne</li>
|
|
<li>champagne-ardenne</li>
|
|
<li>franche-comte</li>
|
|
<li>haute-normandie</li>
|
|
<li>ile-de-france</li>
|
|
<li>languedoc-roussillon</li>
|
|
<li>limousin</li>
|
|
<li>lorraine</li>
|
|
<li>bourgogne</li>
|
|
<li>centre</li>
|
|
<li>midi-pyrenees</li>
|
|
<li>nord-pas-de-calais</li>
|
|
<li>pays-de-la-loire</li>
|
|
<li>picardie</li>
|
|
<li>poitou-charentes</li>
|
|
<li>provence-alpes-cote-dazur</li>
|
|
<li>rhone-alpes</li>
|
|
<br/>
|
|
<li>letzebuerg</li>
|
|
<br/>
|
|
<li>nederland</li>
|
|
<li>drenthe</li>
|
|
<li>flevoland</li>
|
|
<li>friesland</li>
|
|
<li>gelderland</li>
|
|
<li>groningen</li>
|
|
<li>limburg</li>
|
|
<li>noordbrabant</li>
|
|
<li>noordholland</li>
|
|
<li>overijssel</li>
|
|
<li>utrecht</li>
|
|
<li>zeeland</li>
|
|
<li>zuidholland</li>
|
|
<br/>
|
|
<li>norwegen</li>
|
|
<br/>
|
|
<li>portugal</li>
|
|
<br/>
|
|
<li>sverige</li>
|
|
<br/>
|
|
<li>espana</li>
|
|
<br/>
|
|
<li>unitedkingdom</li>
|
|
<li>eastofengland</li>
|
|
<li>eastmidlands</li>
|
|
<li>london</li>
|
|
<li>northeastengland</li>
|
|
<li>northernireland</li>
|
|
<li>northwestengland</li>
|
|
<li>scotland</li>
|
|
<li>southeastengland</li>
|
|
<li>southwestengland</li>
|
|
<li>wales</li>
|
|
<li>westmidlands</li>
|
|
<li>yorkshireandthehumber</li>
|
|
<br/>
|
|
<li>isobaren1</li>
|
|
<li>isobaren2</li>
|
|
<li>isobaren3</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<li><code>define UnwetterKarteMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","currents")}</code></li>
|
|
<ul>
|
|
<li>The second parameter should be one of:
|
|
<ul>
|
|
<li>niederschlag-wolken</li>
|
|
<li>stroemung</li>
|
|
<li>temperatur</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-de</li>
|
|
<li>stroemung-de</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-ch</li>
|
|
<li>stroemung-ch</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-at</li>
|
|
<li>stroemung-at</li>
|
|
<br/>
|
|
<li>neerslag-wolken-nl</li>
|
|
<li>stroming-nl</li>
|
|
<br/>
|
|
<li>nuages-precipitations-fr</li>
|
|
<li>courants-fr</li>
|
|
<br/>
|
|
<li>clouds-precipitation-uk</li>
|
|
<li>currents-uk</li>
|
|
<br/>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<br/><br/>
|
|
</ul>
|
|
<br>
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
=end html
|
|
|
|
=begin html_DE
|
|
|
|
<a name="UWZ"></a>
|
|
<h3>UWZ</h3>
|
|
<ul>
|
|
<a name="UWZdefine"></a>
|
|
Das Modul extrahiert Unwetterwarnungen von <a href="https://www.unwetterzentrale.de">www.unwetterzentrale.de</a>.
|
|
<br/>
|
|
Hierfür wird die selbe Schnittstelle verwendet die auch die Android App <a href="https://www.alertspro.com">Alerts Pro</a> 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.
|
|
<br>
|
|
<i>Es nutzt die Perl-Module HTTP::Request, LWP::UserAgent, JSON, Encode::Guess und HTML::Parse</i>.
|
|
<br/><br/>
|
|
<b>Define</b>
|
|
<ul>
|
|
<br>
|
|
<code>define <Name> UWZ [Ländercode] [Postleitzahl] [INTERVAL]</code>
|
|
<br><br><br>
|
|
Beispiel:
|
|
<br>
|
|
<code>define Unwetterzentrale UWZ DE 86405 3600</code>
|
|
<br>
|
|
|
|
<li><code>[Ländercode]</code>
|
|
<br>
|
|
Mögliche Werte: DE, AT, CH, SEARCH, ...<br/>
|
|
(für ander Länder als Deutschland bitte den SEARCH Parameter nutzen um die AreaID zu ermitteln.)
|
|
</li><br>
|
|
<li><code>[Postleitzahl/AreaID]</code>
|
|
<br>
|
|
Die Postleitzahl/AreaID des Ortes für den Unwetterinformationen abgefragt werden sollen.
|
|
<br>
|
|
</li><br>
|
|
<li><code>[INTERVAL]</code>
|
|
<br>
|
|
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.
|
|
<br>
|
|
</li><br>
|
|
</ul>
|
|
<br>
|
|
|
|
<a name="UWZget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>get <name> Bodenfrost</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Bodenfrostwarnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Extremfrost</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Extremfrostwarnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Gewitter</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Gewitter Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Glaette</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Glaettewarnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Glatteisregen</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Glatteisregen Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Hagel</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Hagel Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Hitze</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Hitze Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Regen</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Regen Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Schneefall</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Schneefall Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Sturm</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Sturm Warnung besteht (active|inactive).
|
|
</li><br>
|
|
<li><code>get <name> Waldbrand</code>
|
|
<br>
|
|
Gibt aus ob aktuell eine Waldbrand Warnung besteht (active|inactive).
|
|
</li><br>
|
|
|
|
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
<b>Get (Search-Mode)</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>get <name> SearchAreaID <gesuchte_stadt></code>
|
|
<br>
|
|
Gibt die AreaID zum eingegebenen Ort aus.
|
|
</li><br>
|
|
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
|
|
|
|
<a name="UWZset"></a>
|
|
<b>Set</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>set <name> update</code>
|
|
<br>
|
|
Startet sofort ein neues Auslesen der Unwetterinformationen.
|
|
</li><br>
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
<a name="UWZattr"></a>
|
|
<b>Attribute</b>
|
|
<ul>
|
|
<br>
|
|
<li><code>download</code>
|
|
<br>
|
|
Download Unwetterkarten während des updates (0|1).
|
|
<br>
|
|
</li>
|
|
<li><code>savepath</code>
|
|
<br>
|
|
Pfad zum speichern der Karten (default: /tmp/).
|
|
<br>
|
|
</li>
|
|
<li><code>maps</code>
|
|
<br>
|
|
Leerzeichen separierte Liste der zu speichernden Karten. Für mögliche Karten siehe <code>UWZAsHtmlKarteLand</code>.
|
|
<br>
|
|
</li>
|
|
<li><code>humanreadable</code>
|
|
<br>
|
|
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)
|
|
<br>
|
|
</li>
|
|
<li><code>lang</code>
|
|
<br>
|
|
Umschalten der angeforderten Sprache für kurz und lange warn text. (de|en|it|fr|es|..).
|
|
<br>
|
|
</li>
|
|
<li><code>sort_readings_by</code>
|
|
<br>
|
|
Sortierreihenfolge der Warnmeldungen. (start|severity|creation).
|
|
<br>
|
|
</li>
|
|
<li><code>htmlsequence</code>
|
|
<br>
|
|
Anzeigereihenfolge der html warnungen. (ascending|descending).
|
|
<br>
|
|
</li>
|
|
<li><code>htmltitle</code>
|
|
<br>
|
|
Titel / Ueberschrift der HTML Ausgabe
|
|
<br>
|
|
</li>
|
|
<li><code>htmltitleclass</code>
|
|
<br>
|
|
css-Class des Titels der HTML Ausgabe
|
|
<br>
|
|
</li>
|
|
<li><code>localiconbase</code>
|
|
<br>
|
|
BaseURL angeben um Warn Icons lokal zu hosten. (Dateityp ist png).
|
|
<br>
|
|
</li>
|
|
<li><code>intervalAtWarnLevel</code>
|
|
<br>
|
|
konfiguriert den Interval je nach WarnLevel. Beispiel: 2=1800,3=900,4=300
|
|
<br>
|
|
</li>
|
|
|
|
<br>
|
|
</ul>
|
|
|
|
<br>
|
|
|
|
<a name="UWZreading"></a>
|
|
<b>Readings</b>
|
|
<ul>
|
|
<br>
|
|
<li><b>Warn_</b><i>0|1|2|3...|9</i><b>_...</b> - aktive Warnmeldungen</li>
|
|
<li><b>WarnCount</b> - Anzahl der aktiven Warnmeldungen</li>
|
|
<li><b>WarnUWZLevel</b> - Gesamt Warn Level </li>
|
|
<li><b>WarnUWZLevel_Color</b> - Gesamt Warn Level Farbe</li>
|
|
<li><b>WarnUWZLevel_Str</b> - Gesamt Warn Level Text</li>
|
|
<li><b>Warn_</b><i>0</i><b>_AltitudeMin</b> - minimum Höhe für Warnung </li>
|
|
<li><b>Warn_</b><i>0</i><b>_AltitudeMax</b> - maximum Höhe für Warnung </li>
|
|
<li><b>Warn_</b><i>0</i><b>_EventID</b> - EventID der Warnung </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation</b> - Warnungs Erzeugung </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation_Date</b> - Warnungs Erzeugungs Datum </li>
|
|
<li><b>Warn_</b><i>0</i><b>_Creation_Time</b> - Warnungs Erzeugungs Zeit </li>
|
|
<li><b>currentIntervalMode</b> - default/warn, aktuell Verwendeter Interval. Internal INTERVAL oder INTERVALWARN</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start</b> - Begin der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start_Date</b> - Startdatum der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Start_Time</b> - Startzeit der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End</b> - Warn Ende</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End_Date</b> - Enddatum der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_End_Time</b> - Endzeit der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Severity</b> - Schwere des Unwetters (0 kein Unwetter, 12 massives Unwetter)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Hail</b> - Hagelwarnung (1|0)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Type</b> - Art des Unwetters</li>
|
|
<li><b>Warn_</b><i>0</i><b>_Type_Str</b> - Art des Unwetters (text)</li>
|
|
<ul>
|
|
<li><b>1</b> - unbekannt</li>
|
|
<li><b>2</b> - Sturm/Orkan</li>
|
|
<li><b>3</b> - Schneefall</li>
|
|
<li><b>4</b> - Regen</li>
|
|
<li><b>5</b> - Extremfrost</li>
|
|
<li><b>6</b> - Waldbrandgefahr</li>
|
|
<li><b>7</b> - Gewitter</li>
|
|
<li><b>8</b> - Glätte</li>
|
|
<li><b>9</b> - Hitze</li>
|
|
<li><b>10</b> - Glatteisregen</li>
|
|
<li><b>11</b> - Bodenfrost</li>
|
|
</ul>
|
|
<li><b>Warn_</b><i>0</i><b>_uwzLevel</b> - Unwetterwarnstufe (0-5)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_uwzLevel_Str</b> - Unwetterwarnstufe (text)</li>
|
|
<li><b>Warn_</b><i>0</i><b>_levelName</b> - Level Warn Name</li>
|
|
<li><b>Warn_</b><i>0</i><b>_ShortText</b> - Kurzbeschreibung der Warnung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_LongText</b> - Ausführliche Unwetterbeschreibung</li>
|
|
<li><b>Warn_</b><i>0</i><b>_IconURL</b> - Kumulierte URL um Warnungs-Icon von <a href="https://www.unwetterzentrale.de">www.unwetterzentrale.de</a> anzuzeigen</li>
|
|
</ul>
|
|
<br>
|
|
|
|
<a name="UWZweblinks"></a>
|
|
<b>Weblinks</b>
|
|
<ul>
|
|
<br>
|
|
|
|
Über die Funktionen <code>UWZAsHtml, UWZAsHtmlLite, UWZAsHtmlFP, UWZAsHtmlKarteLand, UWZAsHtmlMovie</code> wird HTML-Code zur Warnanzeige und Wetterfilme über weblinks erzeugt.
|
|
<br><br><br>
|
|
Beispiele:
|
|
<br>
|
|
<li><code>define UnwetterDetailiert weblink htmlCode {FHEM::UWZ::UWZAsHtml("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterLite weblink htmlCode {FHEM::UWZ::UWZAsHtmlLite("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterFloorplan weblink htmlCode {FHEM::UWZ::UWZAsHtmlFP("Unwetterzentrale")}</code></li>
|
|
<br>
|
|
<li><code>define UnwetterKarteLand weblink htmlCode {FHEM::UWZ::UWZAsHtmlKarteLand("Unwetterzentrale","Bayern")}</code></li>
|
|
<ul>
|
|
<li>Der zweite Parameter kann einer der folgenden sein:
|
|
<ul>
|
|
<li>europa</li>
|
|
<br/>
|
|
<li>deutschland</li>
|
|
<li>deutschland-small</li>
|
|
<li>niedersachsen</li>
|
|
<li>bremen</li>
|
|
<li>bayern</li>
|
|
<li>schleswig-holstein</li>
|
|
<li>hamburg</li>
|
|
<li>mecklenburg-vorpommern</li>
|
|
<li>sachsen</li>
|
|
<li>sachsen-anhalt</li>
|
|
<li>nordrhein-westfalen</li>
|
|
<li>thueringen</li>
|
|
<li>rheinland-pfalz</li>
|
|
<li>saarland</li>
|
|
<li>baden-wuerttemberg</li>
|
|
<li>hessen</li>
|
|
<li>brandenburg</li>
|
|
<li>berlin</li>
|
|
<br/>
|
|
<li>oesterreich</li>
|
|
<li>burgenland</li>
|
|
<li>kaernten</li>
|
|
<li>niederoesterreich</li>
|
|
<li>oberoesterreich</li>
|
|
<li>salzburg</li>
|
|
<li>steiermark</li>
|
|
<li>tirol</li>
|
|
<li>vorarlberg</li>
|
|
<li>wien</li>
|
|
<br/>
|
|
<li>schweiz</li>
|
|
<li>aargau</li>
|
|
<li>appenzell_ausserrhoden</li>
|
|
<li>appenzell_innerrhoden</li>
|
|
<li>basel_landschaft</li>
|
|
<li>basel_stadt</li>
|
|
<li>bern</li>
|
|
<li>fribourg</li>
|
|
<li>geneve</li>
|
|
<li>glarus</li>
|
|
<li>graubuenden</li>
|
|
<li>jura</li>
|
|
<li>luzern</li>
|
|
<li>neuchatel</li>
|
|
<li>nidwalden</li>
|
|
<li>obwalden</li>
|
|
<li>schaffhausen</li>
|
|
<li>schwyz</li>
|
|
<li>solothurn</li>
|
|
<li>stgallen</li>
|
|
<li>ticino</li>
|
|
<li>thurgau</li>
|
|
<li>uri</li>
|
|
<li>waadt</li>
|
|
<li>wallis</li>
|
|
<li>zug</li>
|
|
<li>zuerich</li>
|
|
<br/>
|
|
<li>liechtenstein</li>
|
|
<br/>
|
|
<li>belgique</li>
|
|
<br/>
|
|
<li>denmark</li>
|
|
<br/>
|
|
<li>finnland</li>
|
|
<br/>
|
|
<li>france</li>
|
|
<li>alsace</li>
|
|
<li>aquitaine</li>
|
|
<li>basse-normandie</li>
|
|
<li>bretagne</li>
|
|
<li>champagne-ardenne</li>
|
|
<li>franche-comte</li>
|
|
<li>haute-normandie</li>
|
|
<li>ile-de-france</li>
|
|
<li>languedoc-roussillon</li>
|
|
<li>limousin</li>
|
|
<li>lorraine</li>
|
|
<li>bourgogne</li>
|
|
<li>centre</li>
|
|
<li>midi-pyrenees</li>
|
|
<li>nord-pas-de-calais</li>
|
|
<li>pays-de-la-loire</li>
|
|
<li>picardie</li>
|
|
<li>poitou-charentes</li>
|
|
<li>provence-alpes-cote-dazur</li>
|
|
<li>rhone-alpes</li>
|
|
<br/>
|
|
<li>letzebuerg</li>
|
|
<br/>
|
|
<li>nederland</li>
|
|
<li>drenthe</li>
|
|
<li>flevoland</li>
|
|
<li>friesland</li>
|
|
<li>gelderland</li>
|
|
<li>groningen</li>
|
|
<li>limburg</li>
|
|
<li>noordbrabant</li>
|
|
<li>noordholland</li>
|
|
<li>overijssel</li>
|
|
<li>utrecht</li>
|
|
<li>zeeland</li>
|
|
<li>zuidholland</li>
|
|
<br/>
|
|
<li>norwegen</li>
|
|
<br/>
|
|
<li>portugal</li>
|
|
<br/>
|
|
<li>sverige</li>
|
|
<br/>
|
|
<li>espana</li>
|
|
<br/>
|
|
<li>unitedkingdom</li>
|
|
<li>eastofengland</li>
|
|
<li>eastmidlands</li>
|
|
<li>london</li>
|
|
<li>northeastengland</li>
|
|
<li>northernireland</li>
|
|
<li>northwestengland</li>
|
|
<li>scotland</li>
|
|
<li>southeastengland</li>
|
|
<li>southwestengland</li>
|
|
<li>wales</li>
|
|
<li>westmidlands</li>
|
|
<li>yorkshireandthehumber</li>
|
|
<br/>
|
|
<li>isobaren1</li>
|
|
<li>isobaren2</li>
|
|
<li>isobaren3</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<li><code>define UnwetterKarteMovie weblink htmlCode {FHEM::UWZ::UWZAsHtmlMovie("Unwetterzentrale","niederschlag-wolken-de")}</code></li>
|
|
<ul>
|
|
<li>Der zweite Parameter kann einer der folgenden sein:
|
|
<ul>
|
|
<li>niederschlag-wolken</li>
|
|
<li>stroemung</li>
|
|
<li>temperatur</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-de</li>
|
|
<li>stroemung-de</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-ch</li>
|
|
<li>stroemung-ch</li>
|
|
<br/>
|
|
<li>niederschlag-wolken-at</li>
|
|
<li>stroemung-at</li>
|
|
<br/>
|
|
<li>neerslag-wolken-nl</li>
|
|
<li>stroming-nl</li>
|
|
<br/>
|
|
<li>nuages-precipitations-fr</li>
|
|
<li>courants-fr</li>
|
|
<br/>
|
|
<li>clouds-precipitation-uk</li>
|
|
<li>currents-uk</li>
|
|
<br/>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
<br/><br/>
|
|
</ul>
|
|
<br>
|
|
|
|
|
|
</ul>
|
|
|
|
=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 <fhemdevelopment@cooltux.net>"
|
|
],
|
|
"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
|