mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-03 13:45:36 +00:00
76_SolarForecast: new command get dwdCatalog
git-svn-id: https://svn.fhem.de/fhem/trunk@28513 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
885f39ccb8
commit
6bd9853396
@ -1,5 +1,6 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 76_SolarForecast: new command get dwdCatalog
|
||||||
- feature: 72_FRITZBOX: QAM Informationen bei Cable Boxen
|
- feature: 72_FRITZBOX: QAM Informationen bei Cable Boxen
|
||||||
- bufgix: 72_FRITZBOX: kleinere Fehler bereinigt.
|
- bufgix: 72_FRITZBOX: kleinere Fehler bereinigt.
|
||||||
LAN Geräte ohne IP wurden nicht angezeigt.
|
LAN Geräte ohne IP wurden nicht angezeigt.
|
||||||
|
@ -158,6 +158,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.16.0" => "12.02.2024 new command get dwdCatalog ",
|
||||||
"1.15.5" => "11.02.2024 change forecastQualities output, new limits for 'accurate' and 'spreaded' results from AI ".
|
"1.15.5" => "11.02.2024 change forecastQualities output, new limits for 'accurate' and 'spreaded' results from AI ".
|
||||||
"checkPlantConfig: change common check info output ".
|
"checkPlantConfig: change common check info output ".
|
||||||
"fix load Astro ",
|
"fix load Astro ",
|
||||||
@ -327,6 +328,8 @@ my $csmcache = $root."/FHEM/FhemUtils/PVCsm_SolarForecast_";
|
|||||||
my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt)
|
my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt)
|
||||||
my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt)
|
my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt)
|
||||||
my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten
|
my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten
|
||||||
|
my $dwdcatalog = $root."/FHEM/FhemUtils/DWDcat_SolarForecast"; # Filename-Fragment für DWD Stationskatalog
|
||||||
|
my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Filename-Fragment für DWD Stationskatalog
|
||||||
|
|
||||||
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
||||||
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
||||||
@ -407,6 +410,7 @@ my @dd = qw( none
|
|||||||
consumerPlanning
|
consumerPlanning
|
||||||
consumerSwitching
|
consumerSwitching
|
||||||
consumption
|
consumption
|
||||||
|
dwdComm
|
||||||
epiecesCalc
|
epiecesCalc
|
||||||
graphic
|
graphic
|
||||||
notifyHandling
|
notifyHandling
|
||||||
@ -484,6 +488,7 @@ my %hget = ( # Ha
|
|||||||
solApiData => { fn => \&_getlistSolCastData, needcred => 0 },
|
solApiData => { fn => \&_getlistSolCastData, needcred => 0 },
|
||||||
valDecTree => { fn => \&_getaiDecTree, needcred => 0 },
|
valDecTree => { fn => \&_getaiDecTree, needcred => 0 },
|
||||||
ftuiFramefiles => { fn => \&_ftuiFramefiles, needcred => 0 },
|
ftuiFramefiles => { fn => \&_ftuiFramefiles, needcred => 0 },
|
||||||
|
dwdCatalog => { fn => \&_getdwdCatalog, needcred => 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
my %hattr = ( # Hash für Attr-Funktion
|
my %hattr = ( # Hash für Attr-Funktion
|
||||||
@ -585,6 +590,10 @@ my %hqtxt = (
|
|||||||
DE => qq{Attribut} },
|
DE => qq{Attribut} },
|
||||||
note => { EN => qq{Note},
|
note => { EN => qq{Note},
|
||||||
DE => qq{Hinweis} },
|
DE => qq{Hinweis} },
|
||||||
|
dwdcat => { EN => qq{The Deutscher Wetterdienst Station Catalog},
|
||||||
|
DE => qq{Der Stationskatalog des Deutschen Wetterdienstes} },
|
||||||
|
nrsele => { EN => qq{No. selected entries:},
|
||||||
|
DE => qq{Anzahl ausgewählter Einträge:} },
|
||||||
wfmdcf => { EN => qq{Wait for more days with a consumption figure},
|
wfmdcf => { EN => qq{Wait for more days with a consumption figure},
|
||||||
DE => qq{Warte auf weitere Tage mit einer Verbrauchszahl} },
|
DE => qq{Warte auf weitere Tage mit einer Verbrauchszahl} },
|
||||||
autoct => { EN => qq{Autocorrection:},
|
autoct => { EN => qq{Autocorrection:},
|
||||||
@ -910,6 +919,7 @@ my %hcsr = (
|
|||||||
# $data{$type}{$name}{aidectree}{airaw} # Rohdaten für AI Input = Raw Trainigsdaten
|
# $data{$type}{$name}{aidectree}{airaw} # Rohdaten für AI Input = Raw Trainigsdaten
|
||||||
# $data{$type}{$name}{func} # interne Funktionen
|
# $data{$type}{$name}{func} # interne Funktionen
|
||||||
# $data{$type}{$name}{weatherdata} # temporärer Speicher Wetterdaten
|
# $data{$type}{$name}{weatherdata} # temporärer Speicher Wetterdaten
|
||||||
|
# $data{$type}{$name}{dwdcatalog} # DWD Stationskatalog
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Init Fn
|
# Init Fn
|
||||||
@ -1131,6 +1141,17 @@ sub _readCacheFile {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($cachename eq 'dwdcatalog') {
|
||||||
|
my ($err, $data) = fileRetrieve ($file);
|
||||||
|
|
||||||
|
if (!$err && $data) {
|
||||||
|
$data{$type}{$name}{dwdcatalog} = $data;
|
||||||
|
debugLog ($paref, 'dwdComm', qq{$title restored});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
my ($error, @content) = FileRead ($file);
|
my ($error, @content) = FileRead ($file);
|
||||||
|
|
||||||
if (!$error) {
|
if (!$error) {
|
||||||
@ -2448,6 +2469,7 @@ sub Get {
|
|||||||
my $getlist = "Unknown argument $opt, choose one of ".
|
my $getlist = "Unknown argument $opt, choose one of ".
|
||||||
"valConsumerMaster:#,$cml ".
|
"valConsumerMaster:#,$cml ".
|
||||||
"data:noArg ".
|
"data:noArg ".
|
||||||
|
"dwdCatalog ".
|
||||||
"forecastQualities:noArg ".
|
"forecastQualities:noArg ".
|
||||||
"ftuiFramefiles:noArg ".
|
"ftuiFramefiles:noArg ".
|
||||||
"html:$hol ".
|
"html:$hol ".
|
||||||
@ -3940,6 +3962,350 @@ sub _getlistSolCastData {
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Getter dwdCatalog
|
||||||
|
###############################################################
|
||||||
|
sub _getdwdCatalog {
|
||||||
|
my $paref = shift;
|
||||||
|
my $arg = $paref->{arg} // 'byID';
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
|
||||||
|
my ($aa,$ha) = parseParams ($arg);
|
||||||
|
|
||||||
|
my $sort = 'byID' ~~ @$aa ? 'byID' :
|
||||||
|
'byName' ~~ @$aa ? 'byName' : 'byID';
|
||||||
|
my $export = 'exportgpx' ~~ @$aa ? 'exportgpx' : '';
|
||||||
|
my $force = 'force' ~~ @$aa ? 'force' : '';
|
||||||
|
|
||||||
|
$paref->{sort} = $sort;
|
||||||
|
$paref->{export} = $export;
|
||||||
|
$paref->{filtid} = $ha->{id} ? $ha->{id} : '';
|
||||||
|
$paref->{filtnam} = $ha->{name} ? $ha->{name} : '';
|
||||||
|
$paref->{filtlat} = $ha->{lat} ? $ha->{lat} : '';
|
||||||
|
$paref->{filtlon} = $ha->{lon} ? $ha->{lon} : '';
|
||||||
|
|
||||||
|
my $msg = "The DWD Station Catalog is initially loaded into SolarForecast.\n".
|
||||||
|
"Please execute the command 'get $name $paref->{opt} $arg' again.";
|
||||||
|
|
||||||
|
if ($force) {
|
||||||
|
__dwdStatCatalog_Request ($paref);
|
||||||
|
$msg = "The DWD Station Catalog is initially loaded into SolarForecast.";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) { # Katalog ist geladen
|
||||||
|
return __generateCatOut ($paref);
|
||||||
|
}
|
||||||
|
else { # Katalog nicht geladen -> von File laden
|
||||||
|
_readCacheFile ({ hash => $paref->{hash},
|
||||||
|
name => $name,
|
||||||
|
type => $type,
|
||||||
|
debug => $paref->{debug},
|
||||||
|
file => $dwdcatalog,
|
||||||
|
cachename => 'dwdcatalog',
|
||||||
|
title => 'DWD Station Catalog'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
return __generateCatOut ($paref);
|
||||||
|
}
|
||||||
|
else { # Ladung von File nicht erfolgreich
|
||||||
|
__dwdStatCatalog_Request ($paref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Log3 ($name, 1, "$name > Cat Satz: \n". Dumper $data{$type}{$name}{dwdcatalog});
|
||||||
|
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Ausgabe DWD Katalog formatieren
|
||||||
|
###############################################################
|
||||||
|
sub __generateCatOut {
|
||||||
|
my $paref = shift;
|
||||||
|
my $arg = $paref->{arg};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
my $lang = $paref->{lang};
|
||||||
|
|
||||||
|
my $sort = $paref->{sort};
|
||||||
|
my $export = $paref->{export};
|
||||||
|
my $filtid = $paref->{filtid};
|
||||||
|
my $filtnam = $paref->{filtnam};
|
||||||
|
my $filtlat = $paref->{filtlat};
|
||||||
|
my $filtlon = $paref->{filtlon};
|
||||||
|
|
||||||
|
my $filter = $filtid ? 'id:'.$filtid : '';
|
||||||
|
$filter .= ',' if($filter && $filtnam);
|
||||||
|
$filter .= $filtnam ? 'name:'.$filtnam : '';
|
||||||
|
$filter .= ',' if($filter && $filtlat);
|
||||||
|
$filter .= $filtlat ? 'lat:'.$filtlat : '';
|
||||||
|
$filter .= ',' if($filter && $filtlon);
|
||||||
|
$filter .= $filtlon ? 'lon:'.$filtlon : '';
|
||||||
|
|
||||||
|
my $select = 'sort='.$sort;
|
||||||
|
if ($filter) {
|
||||||
|
$select .= ' filter=';
|
||||||
|
$select .= trim ($filter);
|
||||||
|
}
|
||||||
|
$select .= ' ' if($export);
|
||||||
|
$select .= $export;
|
||||||
|
|
||||||
|
# Katalog Organisation (default ist 'byID)
|
||||||
|
############################################
|
||||||
|
my $temp;
|
||||||
|
|
||||||
|
if ($sort eq 'byName') {
|
||||||
|
for my $id (keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$paref->{id} = $id;
|
||||||
|
next if(___isCatFiltered ($paref));
|
||||||
|
|
||||||
|
my $nid = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$nid}{stnam} = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$nid}{id} = $data{$type}{$name}{dwdcatalog}{$id}{id};
|
||||||
|
$temp->{$nid}{latdec} = $data{$type}{$name}{dwdcatalog}{$id}{latdec}; # Latitude Dezimalgrad
|
||||||
|
$temp->{$nid}{londec} = $data{$type}{$name}{dwdcatalog}{$id}{londec}; # Longitude Dezimalgrad
|
||||||
|
$temp->{$nid}{elev} = $data{$type}{$name}{dwdcatalog}{$id}{elev};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($sort eq 'byID') {
|
||||||
|
for my $id (keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$paref->{id} = $id;
|
||||||
|
next if(___isCatFiltered ($paref));
|
||||||
|
|
||||||
|
$temp->{$id}{stnam} = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$id}{id} = $data{$type}{$name}{dwdcatalog}{$id}{id};
|
||||||
|
$temp->{$id}{latdec} = $data{$type}{$name}{dwdcatalog}{$id}{latdec}; # Latitude Dezimalgrad
|
||||||
|
$temp->{$id}{londec} = $data{$type}{$name}{dwdcatalog}{$id}{londec}; # Longitude Dezimalgrad
|
||||||
|
$temp->{$id}{elev} = $data{$type}{$name}{dwdcatalog}{$id}{elev};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($export eq 'exportgpx') { # DWD Katalog als gpx speichern
|
||||||
|
my @data = ();
|
||||||
|
push @data, '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>';
|
||||||
|
push @data, '<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="FHEM::SolarForecast"';
|
||||||
|
push @data, 'version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
|
||||||
|
push @data, 'xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">';
|
||||||
|
|
||||||
|
for my $idx (sort keys %{$temp}) {
|
||||||
|
my $londec = $temp->{"$idx"}{londec};
|
||||||
|
my $latdec = $temp->{"$idx"}{latdec};
|
||||||
|
my $elev = $temp->{"$idx"}{elev};
|
||||||
|
my $id = $temp->{"$idx"}{id};
|
||||||
|
my $stnam = $temp->{"$idx"}{stnam};
|
||||||
|
|
||||||
|
push @data, qq{<wpt lat="$latdec" lon="$londec">};
|
||||||
|
push @data, qq{ <ele>$elev</ele>};
|
||||||
|
push @data, qq{ <name>$stnam (ID=$id, Latitude=$latdec, Longitude=$londec)</name>};
|
||||||
|
push @data, qq{ <sym>City</sym>};
|
||||||
|
push @data, qq{</wpt>};
|
||||||
|
}
|
||||||
|
|
||||||
|
push @data, '</gpx>';
|
||||||
|
|
||||||
|
my $err = FileWrite ( {FileName => $dwdcatgpx,
|
||||||
|
ForceType => 'file'
|
||||||
|
}, @data
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$err) {
|
||||||
|
debugLog ($paref, 'dwdComm', qq{DWD catalog saved as gpx content: }.$dwdcatgpx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $noe = scalar keys %{$temp};
|
||||||
|
|
||||||
|
## Ausgabe
|
||||||
|
############
|
||||||
|
my $out = '<html>';
|
||||||
|
$out .= '<b>'.encode('utf8', $hqtxt{dwdcat}{$lang}).'</b><br>'; # The Deutscher Wetterdienst Station Catalog
|
||||||
|
$out .= encode('utf8', $hqtxt{nrsele}{$lang}).' '.$noe.'<br>'; # Selected entries
|
||||||
|
$out .= "($select) <br><br>";
|
||||||
|
|
||||||
|
$out .= qq{<table class="roomoverview" style="text-align:left; border:1px solid; padding:5px; border-spacing:5px; margin-left:auto; margin-right:auto;">};
|
||||||
|
$out .= qq{<tr style="font-weight:bold;">};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> ID </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> NAME </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> LATITUDE </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> LONGITUDE </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> ELEVATION </td>};
|
||||||
|
$out .= qq{</tr>};
|
||||||
|
$out .= qq{<tr></tr>};
|
||||||
|
|
||||||
|
for my $key (sort keys %{$temp}) {
|
||||||
|
$out .= qq{<tr>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{id} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; white-space:nowrap;"> $temp->{"$key"}{stnam} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{latdec} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{londec} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{elev} </td>};
|
||||||
|
$out .= qq{</tr>};
|
||||||
|
}
|
||||||
|
|
||||||
|
$out .= qq{</table>};
|
||||||
|
$out .= qq{</html>};
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Ausgabe DWD Katalog Einträge filtern
|
||||||
|
###############################################################
|
||||||
|
sub ___isCatFiltered {
|
||||||
|
my $paref = shift;
|
||||||
|
my $id = $paref->{id};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
|
||||||
|
my $filtid = $paref->{filtid};
|
||||||
|
my $filtnam = $paref->{filtnam};
|
||||||
|
my $filtlat = $paref->{filtlat};
|
||||||
|
my $filtlon = $paref->{filtlon};
|
||||||
|
|
||||||
|
my $isfil = 0;
|
||||||
|
|
||||||
|
$isfil = 1 if($filtid && $id !~ /^$filtid$/ixs);
|
||||||
|
$isfil = 1 if($filtnam && $data{$type}{$name}{dwdcatalog}{$id}{stnam} !~ /^$filtnam$/ixs);
|
||||||
|
$isfil = 1 if($filtlat && $data{$type}{$name}{dwdcatalog}{$id}{latdec} !~ /^$filtlat$/ixs);
|
||||||
|
$isfil = 1 if($filtlon && $data{$type}{$name}{dwdcatalog}{$id}{londec} !~ /^$filtlon$/ixs);
|
||||||
|
|
||||||
|
return $isfil;
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################
|
||||||
|
# Download DWD Stationskatalog
|
||||||
|
# https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication&nn=16102
|
||||||
|
####################################################################################################################
|
||||||
|
sub __dwdStatCatalog_Request {
|
||||||
|
my $paref = shift;
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
|
my $url = "https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication&nn=16102";
|
||||||
|
|
||||||
|
debugLog ($paref, 'dwdComm', "Download DWD Station catalog from URL: $url");
|
||||||
|
|
||||||
|
my $param = {
|
||||||
|
url => $url,
|
||||||
|
timeout => 10,
|
||||||
|
hash => $hash,
|
||||||
|
name => $name,
|
||||||
|
debug => $debug,
|
||||||
|
stc => [gettimeofday],
|
||||||
|
lang => $paref->{lang},
|
||||||
|
method => 'GET',
|
||||||
|
callback => \&__dwdStatCatalog_Response
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($debug =~ /dwdComm/x) {
|
||||||
|
$param->{loglevel} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpUtils_NonblockingGet ($param);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Download DWD Stationskatalog Response
|
||||||
|
# Für die Stationsliste im cfg-Format gilt:
|
||||||
|
# Die Angabe der Längen- und Breitengrade erfolgt in der Form
|
||||||
|
# Grad und Minuten, also beispielsweise wird die Angabe 53◦ 23′
|
||||||
|
# in Grad und Minuten hier mit Punkt als 53.23 repräsentiert.
|
||||||
|
###############################################################
|
||||||
|
sub __dwdStatCatalog_Response {
|
||||||
|
my $paref = shift;
|
||||||
|
my $err = shift;
|
||||||
|
my $data = shift;
|
||||||
|
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $stc = $paref->{stc}; # Startzeit API Abruf
|
||||||
|
my $lang = $paref->{lang};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
|
my $msg;
|
||||||
|
my $sta = [gettimeofday]; # Start Response Verarbeitung
|
||||||
|
|
||||||
|
if ($err ne "") {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elsif ($data ne "") {
|
||||||
|
my @datarr = split "\n", $data;
|
||||||
|
my $type = $hash->{TYPE};
|
||||||
|
|
||||||
|
for my $s (@datarr) {
|
||||||
|
$s = encode ('utf8', $s);
|
||||||
|
|
||||||
|
my ($id, $tail) = split " ", $s, 2;
|
||||||
|
|
||||||
|
next if($id !~ /[A-Z0-9]+$/xs || $id eq 'ID');
|
||||||
|
|
||||||
|
my $ri = rindex ($tail, " ");
|
||||||
|
my $elev = substr ($tail, $ri + 1); # Meereshöhe
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
$ri = rindex ($tail, " ");
|
||||||
|
my $lon = substr ($tail, $ri + 1); # Longitude
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
$ri = rindex ($tail, " ");
|
||||||
|
my $lat = substr ($tail, $ri + 1); # Latitude
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
my ($icao, $stnam) = split " ", $tail, 2; # ICAO = International Civil Aviation Organization, Stationsname
|
||||||
|
|
||||||
|
my ($latg, $latm) = split /\./, $lat; # in Grad und Minuten splitten
|
||||||
|
my ($long, $lonm) = split /\./, $lon;
|
||||||
|
my $latdec = sprintf "%.2f", ($latg + ($latm / 60));
|
||||||
|
my $londec = sprintf "%.2f", ($long + ($lonm / 60));
|
||||||
|
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{id} = $id;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{stnam} = $stnam;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{icao} = $icao;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{lat} = $lat;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{latdec} = $latdec; # Latitude Dezimalgrad
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{lon} = $lon;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{londec} = $londec; # Longitude Dezimalgrad
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{elev} = $elev;
|
||||||
|
}
|
||||||
|
|
||||||
|
$err = writeCacheToFile ($hash, 'dwdcatalog', $dwdcatalog); # DWD Stationskatalog speichern
|
||||||
|
|
||||||
|
if (!$err) {
|
||||||
|
debugLog ($paref, 'dwdComm', qq{DWD catalog saved into file: }.$dwdcatalog);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
}
|
||||||
|
|
||||||
|
_readCacheFile ({ hash => $hash,
|
||||||
|
name => $name,
|
||||||
|
type => $type,
|
||||||
|
debug => $debug,
|
||||||
|
file => $dwdcatalog,
|
||||||
|
cachename => 'dwdcatalog',
|
||||||
|
title => 'DWD Station Catalog'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $prt = sprintf "%.4f", (tv_interval ($stc) - tv_interval ($sta)); # Laufzeit ermitteln
|
||||||
|
debugLog ($paref, 'dwdComm', "DWD Station Catalog retrieval and processing required >$prt< seconds");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
# Getter aiDecTree
|
# Getter aiDecTree
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -4891,9 +5257,26 @@ sub writeCacheToFile {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($cachename eq 'dwdcatalog') {
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$error = fileStore ($data{$type}{$name}{dwdcatalog}, $file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "The DWD Station Catalog is empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
$err = qq{ERROR while writing DWD Station Catalog to file "$file": $error};
|
||||||
|
Log3 ($name, 1, "$name - $err");
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($cachename eq 'plantconfig') {
|
if ($cachename eq 'plantconfig') {
|
||||||
@data = _savePlantConfig ($hash);
|
@data = _savePlantConfig ($hash);
|
||||||
return 'Plant configuration is empty, no data where written' if(!@data);
|
return 'Plant configuration is empty, no data were written' if(!@data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return if(!$data{$type}{$name}{$cachename});
|
return if(!$data{$type}{$name}{$cachename});
|
||||||
@ -16833,6 +17216,44 @@ to ensure that the system configuration is correct.
|
|||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<a id="SolarForecast-get-dwdCatalog"></a>
|
||||||
|
<li><b>dwdCatalog </b> <br><br>
|
||||||
|
The German Weather Service provides a catalog of MOSMIX stations. <br>
|
||||||
|
This command reads the catalog into SolarForecast and saves it in the file
|
||||||
|
./FHEM/FhemUtils/DWDcat_SolarForecast. <br>
|
||||||
|
The catalog can be extensively filtered and saved in GPS Exchange Format (GPX).
|
||||||
|
The latitude and logitude coordinates are displayed in decimal degrees. <br>
|
||||||
|
Regex expressions in the corresponding keys are used for filtering. The Regex is enclosed in
|
||||||
|
^...$ for evaluation. <br>
|
||||||
|
The following parameters can be specified. Without parameters, the entire catalog is output: <br><br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<table>
|
||||||
|
<colgroup> <col width="20%"> <col width="80%"> </colgroup>
|
||||||
|
<tr><td> <b>byID</b> </td><td>The output is sorted by station ID. (default) </td></tr>
|
||||||
|
<tr><td> <b>byName</b> </td><td>The output is sorted by station name. </td></tr>
|
||||||
|
<tr><td> <b>force</b> </td><td>The latest version of the DWD station catalog is loaded into the system. </td></tr>
|
||||||
|
<tr><td> <b>exportgpx</b> </td><td>The (filtered) stations are saved in the file ./FHEM/FhemUtils/DWDcat_SolarForecast.gpx. </td></tr>
|
||||||
|
<tr><td> </td><td>This file can be displayed in the <a href='https://www.j-berkemeier.de/ShowGPX.html' target='_blank'>GPX viewer</a>, for example. </td></tr>
|
||||||
|
<tr><td> <b>id=<Regex></b> </td><td>Filtering is carried out according to station ID. </td></tr>
|
||||||
|
<tr><td> <b>name=<Regex></b> </td><td>Filtering is carried out according to station name. </td></tr>
|
||||||
|
<tr><td> <b>lat=<Regex></b> </td><td>Filtering is carried out according to latitude. </td></tr>
|
||||||
|
<tr><td> <b>lon=<Regex></b> </td><td>Filtering is carried out according to longitude. </td></tr>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<b>Example: </b> <br>
|
||||||
|
get <name> dwdCatalog byName name=ST.* exportgpx lat=(48|49|50|51|52).* lon=([5-9]|1[0-5]).* <br>
|
||||||
|
# filters the stations largely to German locations beginning with "ST" and exports the data in GPS Exchange format
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<a id="SolarForecast-get-forecastQualities"></a>
|
<a id="SolarForecast-get-forecastQualities"></a>
|
||||||
<li><b>forecastQualities </b> <br><br>
|
<li><b>forecastQualities </b> <br><br>
|
||||||
@ -17499,6 +17920,7 @@ to ensure that the system configuration is correct.
|
|||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operations of the internal consumer switching module </td></tr>
|
<tr><td> <b>consumerSwitching</b> </td><td>Operations of the internal consumer switching module </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
||||||
|
<tr><td> <b>dwdComm</b> </td><td>Communication with the website or server of the German Weather Service (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
||||||
<tr><td> <b>graphic</b> </td><td>Module graphic information </td></tr>
|
<tr><td> <b>graphic</b> </td><td>Module graphic information </td></tr>
|
||||||
<tr><td> <b>notifyHandling</b> </td><td>Sequence of event processing in the module </td></tr>
|
<tr><td> <b>notifyHandling</b> </td><td>Sequence of event processing in the module </td></tr>
|
||||||
@ -18915,7 +19337,45 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<a id="SolarForecast-get-data"></a>
|
<a id="SolarForecast-get-data"></a>
|
||||||
<li><b>data </b> <br><br>
|
<li><b>data </b> <br><br>
|
||||||
Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
|
Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<a id="SolarForecast-get-dwdCatalog"></a>
|
||||||
|
<li><b>dwdCatalog </b> <br><br>
|
||||||
|
Der Deutsche Wetterdienst stellt einen Katalog der MOSMIX Stationen zur Verfügung. <br>
|
||||||
|
Mit diesem Kommando wird der Katalog in SolarForecast eingelesen und in der Datei
|
||||||
|
./FHEM/FhemUtils/DWDcat_SolarForecast gespeichert. <br>
|
||||||
|
Der Katalog kann umfangreich gefiltert und im GPS Exchange Format (GPX) gespeichert werden.
|
||||||
|
Die Koordinaten Latitude und Logitude werden in Dezimalgrad ausgegeben. <br>
|
||||||
|
Zur Filterung werden Regex-Ausdrücke in den entsprechenden Schlüsseln verwendet. Der Regex wird zur Auswertung in
|
||||||
|
^...$ eingeschlossen. <br>
|
||||||
|
Folgende Parameter können angegeben werden. Ohne Parameter erfolgt die Ausgabe des gesamten Katalogs: <br><br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<table>
|
||||||
|
<colgroup> <col width="20%"> <col width="80%"> </colgroup>
|
||||||
|
<tr><td> <b>byID</b> </td><td>Die Ausgabe erfolgt sortiert nach Stations-ID. (default) </td></tr>
|
||||||
|
<tr><td> <b>byName</b> </td><td>Die Ausgabe erfolgt sortiert nach Stations-Name. </td></tr>
|
||||||
|
<tr><td> <b>force</b> </td><td>Es wird die neueste Version des DWD Stationskatalogs in das System geladen. </td></tr>
|
||||||
|
<tr><td> <b>exportgpx</b> </td><td>Die (gefilterten) Stationen werden in der Datei ./FHEM/FhemUtils/DWDcat_SolarForecast.gpx gespeichert. </td></tr>
|
||||||
|
<tr><td> </td><td>Diese Datei kann z.B. im <a href='https://www.j-berkemeier.de/ShowGPX.html' target='_blank'>GPX-Viewer</a> dargestellt werden. </td></tr>
|
||||||
|
<tr><td> <b>id=<Regex></b> </td><td>Es erfolgt eine Filterung nach Stations-ID. </td></tr>
|
||||||
|
<tr><td> <b>name=<Regex></b> </td><td>Es erfolgt eine Filterung nach Stations-Name. </td></tr>
|
||||||
|
<tr><td> <b>lat=<Regex></b> </td><td>Es erfolgt eine Filterung nach Latitude. </td></tr>
|
||||||
|
<tr><td> <b>lon=<Regex></b> </td><td>Es erfolgt eine Filterung nach Longitude. </td></tr>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<b>Beispiel: </b> <br>
|
||||||
|
get <name> dwdCatalog byName name=ST.* exportgpx lat=(48|49|50|51|52).* lon=([5-9]|1[0-5]).* <br>
|
||||||
|
# filtert die Stationen weitgehend auf deutsche Orte beginnend mit "ST" und exportiert die Daten im GPS Exchange Format
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -19588,6 +20048,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operationen des internen Consumer Schaltmodul </td></tr>
|
<tr><td> <b>consumerSwitching</b> </td><td>Operationen des internen Consumer Schaltmodul </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
||||||
|
<tr><td> <b>dwdComm</b> </td><td>Kommunikation mit Webseite oder Server des Deutschen Wetterdienst (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
||||||
<tr><td> <b>graphic</b> </td><td>Informationen der Modulgrafik </td></tr>
|
<tr><td> <b>graphic</b> </td><td>Informationen der Modulgrafik </td></tr>
|
||||||
<tr><td> <b>notifyHandling</b> </td><td>Ablauf der Eventverarbeitung im Modul </td></tr>
|
<tr><td> <b>notifyHandling</b> </td><td>Ablauf der Eventverarbeitung im Modul </td></tr>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
# Leerzeichen entfernen: sed -i 's/[[:space:]]*$//' 76_SolarForecast.pm
|
# Leerzeichen entfernen: sed -i 's/[[:space:]]*$//' 76_SolarForecast.pm
|
||||||
#
|
#
|
||||||
#########################################################################################################################
|
#########################################################################################################################
|
||||||
main::LoadModule ('Astro'); # Astro Modul für Sonnenkennzahlen laden
|
main::LoadModule ('Astro'); # Astro Modul für Sonnenkennzahlen laden
|
||||||
|
|
||||||
package FHEM::SolarForecast; ## no critic 'package'
|
package FHEM::SolarForecast; ## no critic 'package'
|
||||||
|
|
||||||
@ -158,6 +158,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.16.0" => "12.02.2024 new command get dwdCatalog ",
|
||||||
"1.15.5" => "11.02.2024 change forecastQualities output, new limits for 'accurate' and 'spreaded' results from AI ".
|
"1.15.5" => "11.02.2024 change forecastQualities output, new limits for 'accurate' and 'spreaded' results from AI ".
|
||||||
"checkPlantConfig: change common check info output ".
|
"checkPlantConfig: change common check info output ".
|
||||||
"fix load Astro ",
|
"fix load Astro ",
|
||||||
@ -327,6 +328,8 @@ my $csmcache = $root."/FHEM/FhemUtils/PVCsm_SolarForecast_";
|
|||||||
my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt)
|
my $scpicache = $root."/FHEM/FhemUtils/ScApi_SolarForecast_"; # Filename-Fragment für Werte aus SolCast API (wird mit Devicename ergänzt)
|
||||||
my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt)
|
my $aitrained = $root."/FHEM/FhemUtils/AItra_SolarForecast_"; # Filename-Fragment für AI Trainingsdaten (wird mit Devicename ergänzt)
|
||||||
my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten
|
my $airaw = $root."/FHEM/FhemUtils/AIraw_SolarForecast_"; # Filename-Fragment für AI Input Daten = Raw Trainigsdaten
|
||||||
|
my $dwdcatalog = $root."/FHEM/FhemUtils/DWDcat_SolarForecast"; # Filename-Fragment für DWD Stationskatalog
|
||||||
|
my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Filename-Fragment für DWD Stationskatalog
|
||||||
|
|
||||||
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
my $aitrblto = 7200; # KI Training BlockingCall Timeout
|
||||||
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
my $aibcthhld = 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
||||||
@ -407,6 +410,7 @@ my @dd = qw( none
|
|||||||
consumerPlanning
|
consumerPlanning
|
||||||
consumerSwitching
|
consumerSwitching
|
||||||
consumption
|
consumption
|
||||||
|
dwdComm
|
||||||
epiecesCalc
|
epiecesCalc
|
||||||
graphic
|
graphic
|
||||||
notifyHandling
|
notifyHandling
|
||||||
@ -484,6 +488,7 @@ my %hget = ( # Ha
|
|||||||
solApiData => { fn => \&_getlistSolCastData, needcred => 0 },
|
solApiData => { fn => \&_getlistSolCastData, needcred => 0 },
|
||||||
valDecTree => { fn => \&_getaiDecTree, needcred => 0 },
|
valDecTree => { fn => \&_getaiDecTree, needcred => 0 },
|
||||||
ftuiFramefiles => { fn => \&_ftuiFramefiles, needcred => 0 },
|
ftuiFramefiles => { fn => \&_ftuiFramefiles, needcred => 0 },
|
||||||
|
dwdCatalog => { fn => \&_getdwdCatalog, needcred => 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
my %hattr = ( # Hash für Attr-Funktion
|
my %hattr = ( # Hash für Attr-Funktion
|
||||||
@ -585,6 +590,10 @@ my %hqtxt = (
|
|||||||
DE => qq{Attribut} },
|
DE => qq{Attribut} },
|
||||||
note => { EN => qq{Note},
|
note => { EN => qq{Note},
|
||||||
DE => qq{Hinweis} },
|
DE => qq{Hinweis} },
|
||||||
|
dwdcat => { EN => qq{The Deutscher Wetterdienst Station Catalog},
|
||||||
|
DE => qq{Der Stationskatalog des Deutschen Wetterdienstes} },
|
||||||
|
nrsele => { EN => qq{No. selected entries:},
|
||||||
|
DE => qq{Anzahl ausgewählter Einträge:} },
|
||||||
wfmdcf => { EN => qq{Wait for more days with a consumption figure},
|
wfmdcf => { EN => qq{Wait for more days with a consumption figure},
|
||||||
DE => qq{Warte auf weitere Tage mit einer Verbrauchszahl} },
|
DE => qq{Warte auf weitere Tage mit einer Verbrauchszahl} },
|
||||||
autoct => { EN => qq{Autocorrection:},
|
autoct => { EN => qq{Autocorrection:},
|
||||||
@ -704,6 +713,8 @@ my %htitles = (
|
|||||||
DE => qq{PV-Überschuß unzureichend} },
|
DE => qq{PV-Überschuß unzureichend} },
|
||||||
plchk => { EN => qq{Configuration check of the plant},
|
plchk => { EN => qq{Configuration check of the plant},
|
||||||
DE => qq{Konfigurationsprüfung der Anlage} },
|
DE => qq{Konfigurationsprüfung der Anlage} },
|
||||||
|
jtsfft => { EN => qq{Open the SolarForecast Forum},
|
||||||
|
DE => qq{Öffne das SolarForecast Forum} },
|
||||||
scaresps => { EN => qq{API request successful},
|
scaresps => { EN => qq{API request successful},
|
||||||
DE => qq{API Abfrage erfolgreich} },
|
DE => qq{API Abfrage erfolgreich} },
|
||||||
scarespf => { EN => qq{API request failed},
|
scarespf => { EN => qq{API request failed},
|
||||||
@ -908,6 +919,7 @@ my %hcsr = (
|
|||||||
# $data{$type}{$name}{aidectree}{airaw} # Rohdaten für AI Input = Raw Trainigsdaten
|
# $data{$type}{$name}{aidectree}{airaw} # Rohdaten für AI Input = Raw Trainigsdaten
|
||||||
# $data{$type}{$name}{func} # interne Funktionen
|
# $data{$type}{$name}{func} # interne Funktionen
|
||||||
# $data{$type}{$name}{weatherdata} # temporärer Speicher Wetterdaten
|
# $data{$type}{$name}{weatherdata} # temporärer Speicher Wetterdaten
|
||||||
|
# $data{$type}{$name}{dwdcatalog} # DWD Stationskatalog
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Init Fn
|
# Init Fn
|
||||||
@ -1129,6 +1141,17 @@ sub _readCacheFile {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($cachename eq 'dwdcatalog') {
|
||||||
|
my ($err, $data) = fileRetrieve ($file);
|
||||||
|
|
||||||
|
if (!$err && $data) {
|
||||||
|
$data{$type}{$name}{dwdcatalog} = $data;
|
||||||
|
debugLog ($paref, 'dwdComm', qq{$title restored});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
my ($error, @content) = FileRead ($file);
|
my ($error, @content) = FileRead ($file);
|
||||||
|
|
||||||
if (!$error) {
|
if (!$error) {
|
||||||
@ -2446,6 +2469,7 @@ sub Get {
|
|||||||
my $getlist = "Unknown argument $opt, choose one of ".
|
my $getlist = "Unknown argument $opt, choose one of ".
|
||||||
"valConsumerMaster:#,$cml ".
|
"valConsumerMaster:#,$cml ".
|
||||||
"data:noArg ".
|
"data:noArg ".
|
||||||
|
"dwdCatalog ".
|
||||||
"forecastQualities:noArg ".
|
"forecastQualities:noArg ".
|
||||||
"ftuiFramefiles:noArg ".
|
"ftuiFramefiles:noArg ".
|
||||||
"html:$hol ".
|
"html:$hol ".
|
||||||
@ -3938,6 +3962,350 @@ sub _getlistSolCastData {
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Getter dwdCatalog
|
||||||
|
###############################################################
|
||||||
|
sub _getdwdCatalog {
|
||||||
|
my $paref = shift;
|
||||||
|
my $arg = $paref->{arg} // 'byID';
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
|
||||||
|
my ($aa,$ha) = parseParams ($arg);
|
||||||
|
|
||||||
|
my $sort = 'byID' ~~ @$aa ? 'byID' :
|
||||||
|
'byName' ~~ @$aa ? 'byName' : 'byID';
|
||||||
|
my $export = 'exportgpx' ~~ @$aa ? 'exportgpx' : '';
|
||||||
|
my $force = 'force' ~~ @$aa ? 'force' : '';
|
||||||
|
|
||||||
|
$paref->{sort} = $sort;
|
||||||
|
$paref->{export} = $export;
|
||||||
|
$paref->{filtid} = $ha->{id} ? $ha->{id} : '';
|
||||||
|
$paref->{filtnam} = $ha->{name} ? $ha->{name} : '';
|
||||||
|
$paref->{filtlat} = $ha->{lat} ? $ha->{lat} : '';
|
||||||
|
$paref->{filtlon} = $ha->{lon} ? $ha->{lon} : '';
|
||||||
|
|
||||||
|
my $msg = "The DWD Station Catalog is initially loaded into SolarForecast.\n".
|
||||||
|
"Please execute the command 'get $name $paref->{opt} $arg' again.";
|
||||||
|
|
||||||
|
if ($force) {
|
||||||
|
__dwdStatCatalog_Request ($paref);
|
||||||
|
$msg = "The DWD Station Catalog is initially loaded into SolarForecast.";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) { # Katalog ist geladen
|
||||||
|
return __generateCatOut ($paref);
|
||||||
|
}
|
||||||
|
else { # Katalog nicht geladen -> von File laden
|
||||||
|
_readCacheFile ({ hash => $paref->{hash},
|
||||||
|
name => $name,
|
||||||
|
type => $type,
|
||||||
|
debug => $paref->{debug},
|
||||||
|
file => $dwdcatalog,
|
||||||
|
cachename => 'dwdcatalog',
|
||||||
|
title => 'DWD Station Catalog'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
return __generateCatOut ($paref);
|
||||||
|
}
|
||||||
|
else { # Ladung von File nicht erfolgreich
|
||||||
|
__dwdStatCatalog_Request ($paref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Log3 ($name, 1, "$name > Cat Satz: \n". Dumper $data{$type}{$name}{dwdcatalog});
|
||||||
|
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Ausgabe DWD Katalog formatieren
|
||||||
|
###############################################################
|
||||||
|
sub __generateCatOut {
|
||||||
|
my $paref = shift;
|
||||||
|
my $arg = $paref->{arg};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
my $lang = $paref->{lang};
|
||||||
|
|
||||||
|
my $sort = $paref->{sort};
|
||||||
|
my $export = $paref->{export};
|
||||||
|
my $filtid = $paref->{filtid};
|
||||||
|
my $filtnam = $paref->{filtnam};
|
||||||
|
my $filtlat = $paref->{filtlat};
|
||||||
|
my $filtlon = $paref->{filtlon};
|
||||||
|
|
||||||
|
my $filter = $filtid ? 'id:'.$filtid : '';
|
||||||
|
$filter .= ',' if($filter && $filtnam);
|
||||||
|
$filter .= $filtnam ? 'name:'.$filtnam : '';
|
||||||
|
$filter .= ',' if($filter && $filtlat);
|
||||||
|
$filter .= $filtlat ? 'lat:'.$filtlat : '';
|
||||||
|
$filter .= ',' if($filter && $filtlon);
|
||||||
|
$filter .= $filtlon ? 'lon:'.$filtlon : '';
|
||||||
|
|
||||||
|
my $select = 'sort='.$sort;
|
||||||
|
if ($filter) {
|
||||||
|
$select .= ' filter=';
|
||||||
|
$select .= trim ($filter);
|
||||||
|
}
|
||||||
|
$select .= ' ' if($export);
|
||||||
|
$select .= $export;
|
||||||
|
|
||||||
|
# Katalog Organisation (default ist 'byID)
|
||||||
|
############################################
|
||||||
|
my $temp;
|
||||||
|
|
||||||
|
if ($sort eq 'byName') {
|
||||||
|
for my $id (keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$paref->{id} = $id;
|
||||||
|
next if(___isCatFiltered ($paref));
|
||||||
|
|
||||||
|
my $nid = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$nid}{stnam} = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$nid}{id} = $data{$type}{$name}{dwdcatalog}{$id}{id};
|
||||||
|
$temp->{$nid}{latdec} = $data{$type}{$name}{dwdcatalog}{$id}{latdec}; # Latitude Dezimalgrad
|
||||||
|
$temp->{$nid}{londec} = $data{$type}{$name}{dwdcatalog}{$id}{londec}; # Longitude Dezimalgrad
|
||||||
|
$temp->{$nid}{elev} = $data{$type}{$name}{dwdcatalog}{$id}{elev};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif ($sort eq 'byID') {
|
||||||
|
for my $id (keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$paref->{id} = $id;
|
||||||
|
next if(___isCatFiltered ($paref));
|
||||||
|
|
||||||
|
$temp->{$id}{stnam} = $data{$type}{$name}{dwdcatalog}{$id}{stnam};
|
||||||
|
$temp->{$id}{id} = $data{$type}{$name}{dwdcatalog}{$id}{id};
|
||||||
|
$temp->{$id}{latdec} = $data{$type}{$name}{dwdcatalog}{$id}{latdec}; # Latitude Dezimalgrad
|
||||||
|
$temp->{$id}{londec} = $data{$type}{$name}{dwdcatalog}{$id}{londec}; # Longitude Dezimalgrad
|
||||||
|
$temp->{$id}{elev} = $data{$type}{$name}{dwdcatalog}{$id}{elev};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($export eq 'exportgpx') { # DWD Katalog als gpx speichern
|
||||||
|
my @data = ();
|
||||||
|
push @data, '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>';
|
||||||
|
push @data, '<gpx xmlns="http://www.topografix.com/GPX/1/1" creator="FHEM::SolarForecast"';
|
||||||
|
push @data, 'version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"';
|
||||||
|
push @data, 'xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">';
|
||||||
|
|
||||||
|
for my $idx (sort keys %{$temp}) {
|
||||||
|
my $londec = $temp->{"$idx"}{londec};
|
||||||
|
my $latdec = $temp->{"$idx"}{latdec};
|
||||||
|
my $elev = $temp->{"$idx"}{elev};
|
||||||
|
my $id = $temp->{"$idx"}{id};
|
||||||
|
my $stnam = $temp->{"$idx"}{stnam};
|
||||||
|
|
||||||
|
push @data, qq{<wpt lat="$latdec" lon="$londec">};
|
||||||
|
push @data, qq{ <ele>$elev</ele>};
|
||||||
|
push @data, qq{ <name>$stnam (ID=$id, Latitude=$latdec, Longitude=$londec)</name>};
|
||||||
|
push @data, qq{ <sym>City</sym>};
|
||||||
|
push @data, qq{</wpt>};
|
||||||
|
}
|
||||||
|
|
||||||
|
push @data, '</gpx>';
|
||||||
|
|
||||||
|
my $err = FileWrite ( {FileName => $dwdcatgpx,
|
||||||
|
ForceType => 'file'
|
||||||
|
}, @data
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$err) {
|
||||||
|
debugLog ($paref, 'dwdComm', qq{DWD catalog saved as gpx content: }.$dwdcatgpx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $noe = scalar keys %{$temp};
|
||||||
|
|
||||||
|
## Ausgabe
|
||||||
|
############
|
||||||
|
my $out = '<html>';
|
||||||
|
$out .= '<b>'.encode('utf8', $hqtxt{dwdcat}{$lang}).'</b><br>'; # The Deutscher Wetterdienst Station Catalog
|
||||||
|
$out .= encode('utf8', $hqtxt{nrsele}{$lang}).' '.$noe.'<br>'; # Selected entries
|
||||||
|
$out .= "($select) <br><br>";
|
||||||
|
|
||||||
|
$out .= qq{<table class="roomoverview" style="text-align:left; border:1px solid; padding:5px; border-spacing:5px; margin-left:auto; margin-right:auto;">};
|
||||||
|
$out .= qq{<tr style="font-weight:bold;">};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> ID </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> NAME </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> LATITUDE </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> LONGITUDE </td>};
|
||||||
|
$out .= qq{<td style="text-decoration:underline; padding: 5px;"> ELEVATION </td>};
|
||||||
|
$out .= qq{</tr>};
|
||||||
|
$out .= qq{<tr></tr>};
|
||||||
|
|
||||||
|
for my $key (sort keys %{$temp}) {
|
||||||
|
$out .= qq{<tr>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{id} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; white-space:nowrap;"> $temp->{"$key"}{stnam} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{latdec} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{londec} </td>};
|
||||||
|
$out .= qq{<td style="padding: 5px; "> $temp->{"$key"}{elev} </td>};
|
||||||
|
$out .= qq{</tr>};
|
||||||
|
}
|
||||||
|
|
||||||
|
$out .= qq{</table>};
|
||||||
|
$out .= qq{</html>};
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Ausgabe DWD Katalog Einträge filtern
|
||||||
|
###############################################################
|
||||||
|
sub ___isCatFiltered {
|
||||||
|
my $paref = shift;
|
||||||
|
my $id = $paref->{id};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
|
||||||
|
my $filtid = $paref->{filtid};
|
||||||
|
my $filtnam = $paref->{filtnam};
|
||||||
|
my $filtlat = $paref->{filtlat};
|
||||||
|
my $filtlon = $paref->{filtlon};
|
||||||
|
|
||||||
|
my $isfil = 0;
|
||||||
|
|
||||||
|
$isfil = 1 if($filtid && $id !~ /^$filtid$/ixs);
|
||||||
|
$isfil = 1 if($filtnam && $data{$type}{$name}{dwdcatalog}{$id}{stnam} !~ /^$filtnam$/ixs);
|
||||||
|
$isfil = 1 if($filtlat && $data{$type}{$name}{dwdcatalog}{$id}{latdec} !~ /^$filtlat$/ixs);
|
||||||
|
$isfil = 1 if($filtlon && $data{$type}{$name}{dwdcatalog}{$id}{londec} !~ /^$filtlon$/ixs);
|
||||||
|
|
||||||
|
return $isfil;
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################################################################################
|
||||||
|
# Download DWD Stationskatalog
|
||||||
|
# https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication&nn=16102
|
||||||
|
####################################################################################################################
|
||||||
|
sub __dwdStatCatalog_Request {
|
||||||
|
my $paref = shift;
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
|
my $url = "https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.cfg?view=nasPublication&nn=16102";
|
||||||
|
|
||||||
|
debugLog ($paref, 'dwdComm', "Download DWD Station catalog from URL: $url");
|
||||||
|
|
||||||
|
my $param = {
|
||||||
|
url => $url,
|
||||||
|
timeout => 10,
|
||||||
|
hash => $hash,
|
||||||
|
name => $name,
|
||||||
|
debug => $debug,
|
||||||
|
stc => [gettimeofday],
|
||||||
|
lang => $paref->{lang},
|
||||||
|
method => 'GET',
|
||||||
|
callback => \&__dwdStatCatalog_Response
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($debug =~ /dwdComm/x) {
|
||||||
|
$param->{loglevel} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpUtils_NonblockingGet ($param);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Download DWD Stationskatalog Response
|
||||||
|
# Für die Stationsliste im cfg-Format gilt:
|
||||||
|
# Die Angabe der Längen- und Breitengrade erfolgt in der Form
|
||||||
|
# Grad und Minuten, also beispielsweise wird die Angabe 53◦ 23′
|
||||||
|
# in Grad und Minuten hier mit Punkt als 53.23 repräsentiert.
|
||||||
|
###############################################################
|
||||||
|
sub __dwdStatCatalog_Response {
|
||||||
|
my $paref = shift;
|
||||||
|
my $err = shift;
|
||||||
|
my $data = shift;
|
||||||
|
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $stc = $paref->{stc}; # Startzeit API Abruf
|
||||||
|
my $lang = $paref->{lang};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
|
my $msg;
|
||||||
|
my $sta = [gettimeofday]; # Start Response Verarbeitung
|
||||||
|
|
||||||
|
if ($err ne "") {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elsif ($data ne "") {
|
||||||
|
my @datarr = split "\n", $data;
|
||||||
|
my $type = $hash->{TYPE};
|
||||||
|
|
||||||
|
for my $s (@datarr) {
|
||||||
|
$s = encode ('utf8', $s);
|
||||||
|
|
||||||
|
my ($id, $tail) = split " ", $s, 2;
|
||||||
|
|
||||||
|
next if($id !~ /[A-Z0-9]+$/xs || $id eq 'ID');
|
||||||
|
|
||||||
|
my $ri = rindex ($tail, " ");
|
||||||
|
my $elev = substr ($tail, $ri + 1); # Meereshöhe
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
$ri = rindex ($tail, " ");
|
||||||
|
my $lon = substr ($tail, $ri + 1); # Longitude
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
$ri = rindex ($tail, " ");
|
||||||
|
my $lat = substr ($tail, $ri + 1); # Latitude
|
||||||
|
$tail = trim (substr ($tail, 0, $ri));
|
||||||
|
|
||||||
|
my ($icao, $stnam) = split " ", $tail, 2; # ICAO = International Civil Aviation Organization, Stationsname
|
||||||
|
|
||||||
|
my ($latg, $latm) = split /\./, $lat; # in Grad und Minuten splitten
|
||||||
|
my ($long, $lonm) = split /\./, $lon;
|
||||||
|
my $latdec = sprintf "%.2f", ($latg + ($latm / 60));
|
||||||
|
my $londec = sprintf "%.2f", ($long + ($lonm / 60));
|
||||||
|
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{id} = $id;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{stnam} = $stnam;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{icao} = $icao;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{lat} = $lat;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{latdec} = $latdec; # Latitude Dezimalgrad
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{lon} = $lon;
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{londec} = $londec; # Longitude Dezimalgrad
|
||||||
|
$data{$type}{$name}{dwdcatalog}{$id}{elev} = $elev;
|
||||||
|
}
|
||||||
|
|
||||||
|
$err = writeCacheToFile ($hash, 'dwdcatalog', $dwdcatalog); # DWD Stationskatalog speichern
|
||||||
|
|
||||||
|
if (!$err) {
|
||||||
|
debugLog ($paref, 'dwdComm', qq{DWD catalog saved into file: }.$dwdcatalog);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log3 ($name, 1, "$name - ERROR - $err");
|
||||||
|
}
|
||||||
|
|
||||||
|
_readCacheFile ({ hash => $hash,
|
||||||
|
name => $name,
|
||||||
|
type => $type,
|
||||||
|
debug => $debug,
|
||||||
|
file => $dwdcatalog,
|
||||||
|
cachename => 'dwdcatalog',
|
||||||
|
title => 'DWD Station Catalog'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $prt = sprintf "%.4f", (tv_interval ($stc) - tv_interval ($sta)); # Laufzeit ermitteln
|
||||||
|
debugLog ($paref, 'dwdComm', "DWD Station Catalog retrieval and processing required >$prt< seconds");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
# Getter aiDecTree
|
# Getter aiDecTree
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -4889,9 +5257,26 @@ sub writeCacheToFile {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($cachename eq 'dwdcatalog') {
|
||||||
|
if (scalar keys %{$data{$type}{$name}{dwdcatalog}}) {
|
||||||
|
$error = fileStore ($data{$type}{$name}{dwdcatalog}, $file);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "The DWD Station Catalog is empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($error) {
|
||||||
|
$err = qq{ERROR while writing DWD Station Catalog to file "$file": $error};
|
||||||
|
Log3 ($name, 1, "$name - $err");
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ($cachename eq 'plantconfig') {
|
if ($cachename eq 'plantconfig') {
|
||||||
@data = _savePlantConfig ($hash);
|
@data = _savePlantConfig ($hash);
|
||||||
return 'Plant configuration is empty, no data where written' if(!@data);
|
return 'Plant configuration is empty, no data were written' if(!@data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return if(!$data{$type}{$name}{$cachename});
|
return if(!$data{$type}{$name}{$cachename});
|
||||||
@ -10147,6 +10532,12 @@ sub _graphicHeader {
|
|||||||
my $chkicon = "<a onClick=$cmdplchk>$img</a>";
|
my $chkicon = "<a onClick=$cmdplchk>$img</a>";
|
||||||
my $chktitle = $htitles{plchk}{$lang};
|
my $chktitle = $htitles{plchk}{$lang};
|
||||||
|
|
||||||
|
## Forum Thread-Icon
|
||||||
|
######################
|
||||||
|
$img = FW_makeImage('time_note@grey');
|
||||||
|
my $fthicon = "<a href='https://forum.fhem.de/index.php?topic=137058.0' target='_blank'>$img</a>";
|
||||||
|
my $fthtitle = $htitles{jtsfft}{$lang};
|
||||||
|
|
||||||
## Update-Icon
|
## Update-Icon
|
||||||
################
|
################
|
||||||
my $upicon = __createUpdateIcon ($paref);
|
my $upicon = __createUpdateIcon ($paref);
|
||||||
@ -10319,10 +10710,11 @@ sub _graphicHeader {
|
|||||||
my $dlink = qq{<a href="$FW_ME$FW_subdir?detail=$name">$alias</a>};
|
my $dlink = qq{<a href="$FW_ME$FW_subdir?detail=$name">$alias</a>};
|
||||||
|
|
||||||
$header .= qq{<tr>};
|
$header .= qq{<tr>};
|
||||||
$header .= qq{<td colspan="2" align="left" $dstyle> <b>$dlink</b> </td>};
|
$header .= qq{<td colspan="1" align="left" $dstyle> <b>$dlink</b> </td>};
|
||||||
$header .= qq{<td colspan="1" align="left" title="$chktitle" $dstyle> $chkicon </td>};
|
$header .= qq{<td colspan="1" align="right" title="$chktitle" $dstyle> $chkicon </td>};
|
||||||
$header .= qq{<td colspan="3" align="left" $dstyle> $lupt $lup $upicon </td>};
|
$header .= qq{<td colspan="1" align="left" title="$fthtitle" $dstyle> $fthicon </td>};
|
||||||
$header .= qq{<td colspan="3" align="right" $dstyle> $api </td>};
|
$header .= qq{<td colspan="3" align="left" $dstyle> $lupt $lup $upicon </td>};
|
||||||
|
$header .= qq{<td colspan="3" align="right" $dstyle> $api </td>};
|
||||||
$header .= qq{</tr>};
|
$header .= qq{</tr>};
|
||||||
$header .= qq{<tr>};
|
$header .= qq{<tr>};
|
||||||
$header .= qq{<td colspan="3" align="left" $dstyle> $sriseimg $srisetxt $ssetimg $ssettxt </td>};
|
$header .= qq{<td colspan="3" align="left" $dstyle> $sriseimg $srisetxt $ssetimg $ssettxt </td>};
|
||||||
@ -12636,10 +13028,7 @@ sub _aiGetSpread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $pvaifc = $pos && $neg ? sprintf "%.0f", (($pos + $neg) / 2) :
|
my $pvaifc = $pos && $neg ? sprintf "%.0f", (($pos + $neg) / 2) : undef;
|
||||||
$pos ? sprintf "%.0f", $pos :
|
|
||||||
$neg ? sprintf "%.0f", $neg :
|
|
||||||
undef;
|
|
||||||
|
|
||||||
if (defined $pvaifc) {
|
if (defined $pvaifc) {
|
||||||
debugLog ($paref, 'aiData', qq{AI determined average result: pvaifc: $pvaifc Wh (hod: $hod, sunalt: $sunalt, wcc: $wcc, wrp: $wrp, temp: $temp)});
|
debugLog ($paref, 'aiData', qq{AI determined average result: pvaifc: $pvaifc Wh (hod: $hod, sunalt: $sunalt, wcc: $wcc, wrp: $wrp, temp: $temp)});
|
||||||
@ -16827,6 +17216,44 @@ to ensure that the system configuration is correct.
|
|||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<a id="SolarForecast-get-dwdCatalog"></a>
|
||||||
|
<li><b>dwdCatalog </b> <br><br>
|
||||||
|
The German Weather Service provides a catalog of MOSMIX stations. <br>
|
||||||
|
This command reads the catalog into SolarForecast and saves it in the file
|
||||||
|
./FHEM/FhemUtils/DWDcat_SolarForecast. <br>
|
||||||
|
The catalog can be extensively filtered and saved in GPS Exchange Format (GPX).
|
||||||
|
The latitude and logitude coordinates are displayed in decimal degrees. <br>
|
||||||
|
Regex expressions in the corresponding keys are used for filtering. The Regex is enclosed in
|
||||||
|
^...$ for evaluation. <br>
|
||||||
|
The following parameters can be specified. Without parameters, the entire catalog is output: <br><br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<table>
|
||||||
|
<colgroup> <col width="20%"> <col width="80%"> </colgroup>
|
||||||
|
<tr><td> <b>byID</b> </td><td>The output is sorted by station ID. (default) </td></tr>
|
||||||
|
<tr><td> <b>byName</b> </td><td>The output is sorted by station name. </td></tr>
|
||||||
|
<tr><td> <b>force</b> </td><td>The latest version of the DWD station catalog is loaded into the system. </td></tr>
|
||||||
|
<tr><td> <b>exportgpx</b> </td><td>The (filtered) stations are saved in the file ./FHEM/FhemUtils/DWDcat_SolarForecast.gpx. </td></tr>
|
||||||
|
<tr><td> </td><td>This file can be displayed in the <a href='https://www.j-berkemeier.de/ShowGPX.html' target='_blank'>GPX viewer</a>, for example. </td></tr>
|
||||||
|
<tr><td> <b>id=<Regex></b> </td><td>Filtering is carried out according to station ID. </td></tr>
|
||||||
|
<tr><td> <b>name=<Regex></b> </td><td>Filtering is carried out according to station name. </td></tr>
|
||||||
|
<tr><td> <b>lat=<Regex></b> </td><td>Filtering is carried out according to latitude. </td></tr>
|
||||||
|
<tr><td> <b>lon=<Regex></b> </td><td>Filtering is carried out according to longitude. </td></tr>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<b>Example: </b> <br>
|
||||||
|
get <name> dwdCatalog byName name=ST.* exportgpx lat=(48|49|50|51|52).* lon=([5-9]|1[0-5]).* <br>
|
||||||
|
# filters the stations largely to German locations beginning with "ST" and exports the data in GPS Exchange format
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<a id="SolarForecast-get-forecastQualities"></a>
|
<a id="SolarForecast-get-forecastQualities"></a>
|
||||||
<li><b>forecastQualities </b> <br><br>
|
<li><b>forecastQualities </b> <br><br>
|
||||||
@ -17493,6 +17920,7 @@ to ensure that the system configuration is correct.
|
|||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operations of the internal consumer switching module </td></tr>
|
<tr><td> <b>consumerSwitching</b> </td><td>Operations of the internal consumer switching module </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
||||||
|
<tr><td> <b>dwdComm</b> </td><td>Communication with the website or server of the German Weather Service (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
||||||
<tr><td> <b>graphic</b> </td><td>Module graphic information </td></tr>
|
<tr><td> <b>graphic</b> </td><td>Module graphic information </td></tr>
|
||||||
<tr><td> <b>notifyHandling</b> </td><td>Sequence of event processing in the module </td></tr>
|
<tr><td> <b>notifyHandling</b> </td><td>Sequence of event processing in the module </td></tr>
|
||||||
@ -18909,7 +19337,45 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<a id="SolarForecast-get-data"></a>
|
<a id="SolarForecast-get-data"></a>
|
||||||
<li><b>data </b> <br><br>
|
<li><b>data </b> <br><br>
|
||||||
Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
|
Startet die Datensammlung zur Bestimmung der solaren Vorhersage und anderer Werte.
|
||||||
</li>
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<a id="SolarForecast-get-dwdCatalog"></a>
|
||||||
|
<li><b>dwdCatalog </b> <br><br>
|
||||||
|
Der Deutsche Wetterdienst stellt einen Katalog der MOSMIX Stationen zur Verfügung. <br>
|
||||||
|
Mit diesem Kommando wird der Katalog in SolarForecast eingelesen und in der Datei
|
||||||
|
./FHEM/FhemUtils/DWDcat_SolarForecast gespeichert. <br>
|
||||||
|
Der Katalog kann umfangreich gefiltert und im GPS Exchange Format (GPX) gespeichert werden.
|
||||||
|
Die Koordinaten Latitude und Logitude werden in Dezimalgrad ausgegeben. <br>
|
||||||
|
Zur Filterung werden Regex-Ausdrücke in den entsprechenden Schlüsseln verwendet. Der Regex wird zur Auswertung in
|
||||||
|
^...$ eingeschlossen. <br>
|
||||||
|
Folgende Parameter können angegeben werden. Ohne Parameter erfolgt die Ausgabe des gesamten Katalogs: <br><br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<table>
|
||||||
|
<colgroup> <col width="20%"> <col width="80%"> </colgroup>
|
||||||
|
<tr><td> <b>byID</b> </td><td>Die Ausgabe erfolgt sortiert nach Stations-ID. (default) </td></tr>
|
||||||
|
<tr><td> <b>byName</b> </td><td>Die Ausgabe erfolgt sortiert nach Stations-Name. </td></tr>
|
||||||
|
<tr><td> <b>force</b> </td><td>Es wird die neueste Version des DWD Stationskatalogs in das System geladen. </td></tr>
|
||||||
|
<tr><td> <b>exportgpx</b> </td><td>Die (gefilterten) Stationen werden in der Datei ./FHEM/FhemUtils/DWDcat_SolarForecast.gpx gespeichert. </td></tr>
|
||||||
|
<tr><td> </td><td>Diese Datei kann z.B. im <a href='https://www.j-berkemeier.de/ShowGPX.html' target='_blank'>GPX-Viewer</a> dargestellt werden. </td></tr>
|
||||||
|
<tr><td> <b>id=<Regex></b> </td><td>Es erfolgt eine Filterung nach Stations-ID. </td></tr>
|
||||||
|
<tr><td> <b>name=<Regex></b> </td><td>Es erfolgt eine Filterung nach Stations-Name. </td></tr>
|
||||||
|
<tr><td> <b>lat=<Regex></b> </td><td>Es erfolgt eine Filterung nach Latitude. </td></tr>
|
||||||
|
<tr><td> <b>lon=<Regex></b> </td><td>Es erfolgt eine Filterung nach Longitude. </td></tr>
|
||||||
|
</table>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<b>Beispiel: </b> <br>
|
||||||
|
get <name> dwdCatalog byName name=ST.* exportgpx lat=(48|49|50|51|52).* lon=([5-9]|1[0-5]).* <br>
|
||||||
|
# filtert die Stationen weitgehend auf deutsche Orte beginnend mit "ST" und exportiert die Daten im GPS Exchange Format
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -19582,6 +20048,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operationen des internen Consumer Schaltmodul </td></tr>
|
<tr><td> <b>consumerSwitching</b> </td><td>Operationen des internen Consumer Schaltmodul </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
||||||
|
<tr><td> <b>dwdComm</b> </td><td>Kommunikation mit Webseite oder Server des Deutschen Wetterdienst (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
||||||
<tr><td> <b>graphic</b> </td><td>Informationen der Modulgrafik </td></tr>
|
<tr><td> <b>graphic</b> </td><td>Informationen der Modulgrafik </td></tr>
|
||||||
<tr><td> <b>notifyHandling</b> </td><td>Ablauf der Eventverarbeitung im Modul </td></tr>
|
<tr><td> <b>notifyHandling</b> </td><td>Ablauf der Eventverarbeitung im Modul </td></tr>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<gpx version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
<gpx version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
<wpt lat="70.56" lon="-8.40">
|
<wpt lat="70.56" lon="-8.40">
|
||||||
<name>01001 - JAN MAYEN</name>
|
<name>01001 - JAN MAYEN</name>
|
||||||
</wpt>
|
</wpt>
|
||||||
<wpt lat="78.15" lon="15.28">
|
<wpt lat="78.15" lon="15.28">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user