mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-09 20:57:11 +00:00
76_SolarForecast: graphicHeaderOwnspec: can add set/attr commands, new setter consumerNewPlanning
git-svn-id: https://svn.fhem.de/fhem/trunk@28174 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
1fb994d013
commit
4db23a2307
@ -1,5 +1,7 @@
|
||||
# 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.
|
||||
- feature: 76_SolarForecast: graphicHeaderOwnspec: can add set/attr commands,
|
||||
new setter consumerNewPlanning
|
||||
- feature: 72_FB_CALLMONITOR commandRef
|
||||
- feature: 72_FRITZBOX set <name> lockFilterProfile ...
|
||||
- feature: 72_FRITZBOX set <name> energyMode ...
|
||||
|
@ -94,6 +94,9 @@ BEGIN {
|
||||
FmtDateTime
|
||||
FW_makeImage
|
||||
getKeyValue
|
||||
getAllAttr
|
||||
getAllGets
|
||||
getAllSets
|
||||
HttpUtils_NonblockingGet
|
||||
init_done
|
||||
InternalTimer
|
||||
@ -119,8 +122,10 @@ BEGIN {
|
||||
FW_directNotify
|
||||
FW_ME
|
||||
FW_subdir
|
||||
FW_pH
|
||||
FW_room
|
||||
FW_detail
|
||||
FW_widgetFallbackFn
|
||||
FW_wname
|
||||
)
|
||||
);
|
||||
@ -144,6 +149,7 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"1.1.0" => "14.11.2023 graphicHeaderOwnspec: possible add set/attr commands, new setter consumerNewPlanning ",
|
||||
"1.0.10" => "31.10.2023 fix warnings, edit comref ",
|
||||
"1.0.9" => "29.10.2023 _aiGetSpread: set spread from 50 to 20 ",
|
||||
"1.0.8" => "22.10.2023 codechange: add central readings store array, new function storeReading, writeCacheToFile ".
|
||||
@ -442,6 +448,8 @@ my $kJtokWh = 0.00027778;
|
||||
my $defmaxvar = 0.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor
|
||||
my $definterval = 70; # Standard Abfrageintervall
|
||||
my $defslidenum = 3; # max. Anzahl der Arrayelemente in Schieberegistern
|
||||
my $webCmdFn = 'FW_widgetFallbackFn'; # FHEMWEB Widgets Funktion
|
||||
my @attrreadings = (); # Array der Hilfsreadings als Attributspeicher
|
||||
|
||||
my $pvhcache = $attr{global}{modpath}."/FHEM/FhemUtils/PVH_SolarForecast_"; # Filename-Fragment für PV History (wird mit Devicename ergänzt)
|
||||
my $pvccache = $attr{global}{modpath}."/FHEM/FhemUtils/PVC_SolarForecast_"; # Filename-Fragment für PV Circular (wird mit Devicename ergänzt)
|
||||
@ -528,12 +536,15 @@ my @dd = qw( none
|
||||
radiationProcess
|
||||
saveData2Cache
|
||||
);
|
||||
|
||||
my $allwidgets = 'icon|sortable|uzsu|knob|noArg|time|text|slider|multiple|select|bitfield|widgetList|colorpicker';
|
||||
|
||||
# Steuerhashes
|
||||
###############
|
||||
|
||||
my %hset = ( # Hash der Set-Funktion
|
||||
consumerImmediatePlanning => { fn => \&_setconsumerImmediatePlanning },
|
||||
consumerNewPlanning => { fn => \&_setconsumerNewPlanning },
|
||||
currentWeatherDev => { fn => \&_setcurrentWeatherDev },
|
||||
currentRadiationAPI => { fn => \&_setcurrentRadiationAPI },
|
||||
modulePeakString => { fn => \&_setmodulePeakString },
|
||||
@ -1302,6 +1313,7 @@ sub Set {
|
||||
my $ipai = isPrepared4AI ($hash);
|
||||
$setlist = "Unknown argument $opt, choose one of ".
|
||||
"consumerImmediatePlanning:$coms ".
|
||||
"consumerNewPlanning:$coms ".
|
||||
"currentWeatherDev:$fcd ".
|
||||
"currentRadiationAPI:$rdd ".
|
||||
"currentBatteryDev:textField-long ".
|
||||
@ -1379,7 +1391,7 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
|
||||
my $type = $paref->{type};
|
||||
my $opt = $paref->{opt};
|
||||
my $c = $paref->{prop};
|
||||
my $evt = $paref->{prop1} // 1;
|
||||
my $evt = $paref->{prop1} // 0; # geändert V 1.1.0 - 1 -> 0
|
||||
|
||||
return qq{no consumer number specified} if(!$c);
|
||||
return qq{no valid consumer id "$c"} if(!ConsumerVal ($hash, $c, "name", ""));
|
||||
@ -1430,6 +1442,29 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Setter consumerNewPlanning
|
||||
################################################################
|
||||
sub _setconsumerNewPlanning { ## no critic "not used"
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $paref->{name};
|
||||
my $c = $paref->{prop};
|
||||
my $evt = $paref->{prop1} // 0; # geändert V 1.1.0 - 1 -> 0
|
||||
|
||||
return qq{no consumer number specified} if(!$c);
|
||||
return qq{no valid consumer id "$c"} if(!ConsumerVal ($hash, $c, 'name', ''));
|
||||
|
||||
if ($c) {
|
||||
deleteConsumerPlanning ($hash, $c);
|
||||
writeCacheToFile ($hash, 'consumers', $csmcache.$name); # Cache File Consumer schreiben
|
||||
}
|
||||
|
||||
centralTask ($hash, $evt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Setter currentWeatherDev (Wetterdaten)
|
||||
################################################################
|
||||
@ -2280,7 +2315,7 @@ sub _setreset { ## no critic "not used"
|
||||
delete $data{$type}{$name}{current}{powerbatin};
|
||||
delete $data{$type}{$name}{current}{batcharge};
|
||||
|
||||
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
|
||||
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
|
||||
}
|
||||
|
||||
if ($prop eq 'currentInverterDev') {
|
||||
@ -2289,7 +2324,7 @@ sub _setreset { ## no critic "not used"
|
||||
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
|
||||
}
|
||||
|
||||
if ($prop eq 'consumerPlanning') { # Verbraucherplanung resetten
|
||||
if ($prop eq 'consumerPlanning') { # Verbraucherplanung resetten
|
||||
my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben
|
||||
|
||||
if ($c) {
|
||||
@ -2320,7 +2355,7 @@ sub _setreset { ## no critic "not used"
|
||||
}
|
||||
}
|
||||
|
||||
writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben
|
||||
writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben
|
||||
}
|
||||
|
||||
createAssociatedWith ($hash);
|
||||
@ -3860,7 +3895,8 @@ sub _getlistPVHistory {
|
||||
|
||||
my $ret = listDataPool ($hash, 'pvhist', $arg);
|
||||
$ret .= lineFromSpaces ($ret, 20);
|
||||
|
||||
$ret =~ s/\n/<br>/g;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@ -3886,7 +3922,7 @@ sub _getlistNextHours {
|
||||
|
||||
my $ret = listDataPool ($hash, 'nexthours');
|
||||
$ret .= lineFromSpaces ($ret, 10);
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@ -5031,7 +5067,10 @@ sub _specialActivities {
|
||||
deleteReadingspec ($hash, "Today_MaxPVforecast.*");
|
||||
deleteReadingspec ($hash, "Today_PVdeviation");
|
||||
deleteReadingspec ($hash, "Today_PVreal");
|
||||
|
||||
|
||||
for my $atr (@attrreadings) {
|
||||
deleteReadingspec ($hash, $atr);
|
||||
}
|
||||
|
||||
for my $n (1..24) {
|
||||
$n = sprintf "%02d", $n;
|
||||
@ -9072,6 +9111,9 @@ sub __createOwnSpec {
|
||||
my $show = $hdrDetail =~ /all|own/xs ? 1 : 0;
|
||||
|
||||
return if(!$spec || !$show);
|
||||
|
||||
my $allsets = getAllSets ($name);
|
||||
my $allattrs = getAllAttr ($name);
|
||||
|
||||
my @fields = split (/\s+/sx, $spec);
|
||||
|
||||
@ -9102,27 +9144,37 @@ sub __createOwnSpec {
|
||||
next;
|
||||
}
|
||||
|
||||
($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($name, $h->{$k}{rdg}, '');
|
||||
}
|
||||
|
||||
if ($uatr eq 'kWh') {
|
||||
for (my $r = 0 ; $r < $vinr; $r++) {
|
||||
next if(!$u->{$r});
|
||||
|
||||
if ($u->{$r} =~ /^Wh/xs) {
|
||||
$v->{$r} = sprintf "%.1f",($v->{$r} / 1000);
|
||||
$u->{$r} = 'kWh';
|
||||
my $setcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allsets, 'set');
|
||||
|
||||
if ($setcmd) {
|
||||
$v->{$k} = $setcmd;
|
||||
$u->{$k} = q{};
|
||||
next;
|
||||
}
|
||||
|
||||
my $attrcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allattrs, 'attr');
|
||||
|
||||
if ($attrcmd) {
|
||||
$v->{$k} = $attrcmd;
|
||||
$u->{$k} = q{};
|
||||
next;
|
||||
}
|
||||
|
||||
($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($name, $h->{$k}{rdg}, ' ');
|
||||
|
||||
next if(!$u->{$k});
|
||||
|
||||
if ($uatr eq 'kWh') {
|
||||
if ($u->{$k} =~ /^Wh/xs) {
|
||||
$v->{$k} = sprintf "%.1f",($v->{$k} / 1000);
|
||||
$u->{$k} = 'kWh';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($uatr eq 'Wh') {
|
||||
for (my $r = 0 ; $r < $vinr; $r++) {
|
||||
next if(!$u->{$r});
|
||||
|
||||
if ($u->{$r} =~ /^kWh/xs) {
|
||||
$v->{$r} = sprintf "%.0f",($v->{$r} * 1000);
|
||||
$u->{$r} = 'Wh';
|
||||
if ($uatr eq 'Wh') {
|
||||
if ($u->{$k} =~ /^kWh/xs) {
|
||||
$v->{$k} = sprintf "%.0f",($v->{$k} * 1000);
|
||||
$u->{$k} = 'Wh';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9143,6 +9195,67 @@ sub __createOwnSpec {
|
||||
return $ownv;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# liefert ein FHEMWEB set/attr Widget zurück
|
||||
################################################################
|
||||
sub ___getFWwidget {
|
||||
my $name = shift;
|
||||
my $elm = shift; # Element
|
||||
my $allc = shift; # Kommandovorrat -> ist Element enthalten?
|
||||
my $ctyp = shift // 'set'; # Kommandotyp: set/attr
|
||||
|
||||
my $widget = '';
|
||||
|
||||
my ($current, $reading);
|
||||
|
||||
if ($allc =~ /$elm:?(.*?)\s/xs) {
|
||||
my $arg = $1;
|
||||
$arg = 'textFieldNL' if(!$arg);
|
||||
|
||||
if ($arg !~ /^\#/xs && $arg !~ /^$allwidgets/xs) {
|
||||
$arg = '#,'.$arg;
|
||||
}
|
||||
|
||||
if ($ctyp eq 'attr') {
|
||||
$current = AttrVal ($name, $elm, '');
|
||||
$reading = '.'.$elm;
|
||||
|
||||
push @attrreadings, $reading;
|
||||
readingsSingleUpdate ($defs{$name}, $reading, $current, 0);
|
||||
}
|
||||
|
||||
no strict "refs"; ## no critic 'NoStrict'
|
||||
$widget = &{$webCmdFn} ($FW_wname, $name, "", $elm, $arg);
|
||||
use strict "refs";
|
||||
|
||||
if ($widget) {
|
||||
$widget =~ s,^<td[^>]*>(.*)</td>$,$1,x;
|
||||
$widget =~ s,></div>, type='$ctyp'></div>,x;
|
||||
}
|
||||
else {
|
||||
$widget = FW_pH ("cmd=$ctyp $name $elm", $elm, 0, "", 1, 1);
|
||||
}
|
||||
|
||||
if ($ctyp eq 'attr') {
|
||||
my ($sc) = $widget =~ /current='(.*?)'/xs;
|
||||
my ($sr) = $widget =~ /reading='(.*?)'/xs;
|
||||
$widget =~ s/$sc/$current/ if(defined $sc);
|
||||
$widget =~ s/$sr/$reading/ if(defined $sr);
|
||||
}
|
||||
|
||||
if ($arg eq 'textField' || $arg eq 'textField-long') { # Label (Reading) ausblenden -> siehe fhemweb.js function FW_createTextField Zeile 1657
|
||||
$widget =~ s/arg='textField/arg='textFieldNL/xs;
|
||||
}
|
||||
|
||||
if ($arg =~ 'slider') { # Widget slider in selectnumbers für Kopfgrafik umsetzen
|
||||
my ($wid, $min, $step, $max, $float) = split ",", $arg;
|
||||
$widget =~ s/arg='(.*?)'/arg='selectnumbers,$min,$step,$max,0,lin'/xs;
|
||||
}
|
||||
}
|
||||
|
||||
return $widget;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Consumer in forecastGraphic (Balken) anzeigen
|
||||
# (Hat zur Zeit keine Wirkung !)
|
||||
@ -9448,8 +9561,8 @@ sub _beamGraphicFirstHour {
|
||||
|
||||
my $day;
|
||||
|
||||
my $t = NexthoursVal ($hash, "NextHour00", "starttime", '0000-00-00 24');
|
||||
my ($year,$month,$day_str,$thishour) = $t =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x;
|
||||
my $stt = NexthoursVal ($hash, "NextHour00", "starttime", '0000-00-00 24');
|
||||
my ($year,$month,$day_str,$thishour) = $stt =~ m/(\d{4})-(\d{2})-(\d{2})\s(\d{2})/x;
|
||||
my ($val1,$val2,$val3,$val4) = (0,0,0,0);
|
||||
|
||||
$thishour++;
|
||||
@ -9489,7 +9602,7 @@ sub _beamGraphicFirstHour {
|
||||
$val3 = CircularVal ($hash, $hfcg->{0}{time_str}, 'gcons', 0);
|
||||
$val4 = CircularVal ($hash, $hfcg->{0}{time_str}, 'confc', 0);
|
||||
|
||||
$hfcg->{0}{weather} = CircularVal ($hash, $hfcg->{0}{time_str}, "weatherid", 999);
|
||||
$hfcg->{0}{weather} = CircularVal ($hash, $hfcg->{0}{time_str}, 'weatherid', 999);
|
||||
#$val4 = (ReadingsVal($name,"ThisHour_IsConsumptionRecommended",'no') eq 'yes' ) ? $icon : 999;
|
||||
}
|
||||
|
||||
@ -9554,14 +9667,14 @@ sub _beamGraphicRemainingHours {
|
||||
$hfcg->{$i}{wcc} = HistoryVal ($hash, $ds, $hfcg->{$i}{time_str}, 'wcc', '-');
|
||||
}
|
||||
else {
|
||||
$nh = sprintf('%02d', $i+$offset);
|
||||
$nh = sprintf '%02d', $i + $offset;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$nh = sprintf('%02d', $i);
|
||||
$nh = sprintf '%02d', $i;
|
||||
}
|
||||
|
||||
if (defined($nh)) {
|
||||
if (defined $nh) {
|
||||
$val1 = NexthoursVal ($hash, 'NextHour'.$nh, 'pvfc', 0);
|
||||
$val4 = NexthoursVal ($hash, 'NextHour'.$nh, 'confc', 0);
|
||||
$hfcg->{$i}{weather} = NexthoursVal ($hash, 'NextHour'.$nh, 'weatherid', 999);
|
||||
@ -9638,15 +9751,15 @@ sub _beamGraphic {
|
||||
if($show_diff eq 'top') { # Zusätzliche Zeile Ertrag - Verbrauch
|
||||
$ret .= "<tr class='$htr{$m}{cl}'><td class='solarfc'></td>";
|
||||
my $ii;
|
||||
for my $i (0..($maxhours*2)-1) { # gleiche Bedingung wie oben
|
||||
next if (!$show_night && ($hfcg->{$i}{weather} > 99)
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2});
|
||||
for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben
|
||||
next if(!$show_night && $hfcg->{$i}{weather} > 99
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2});
|
||||
$ii++; # wieviele Stunden haben wir bisher angezeigt ?
|
||||
|
||||
last if ($ii > $maxhours); # vorzeitiger Abbruch
|
||||
|
||||
$val = formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather});
|
||||
$val = formatVal6 ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather});
|
||||
|
||||
if ($val ne ' ') { # Forum: https://forum.fhem.de/index.php/topic,117864.msg1166215.html#msg1166215
|
||||
$val = $hfcg->{$i}{diff} < 0 ? '<b>'.$val.'<b/>' :
|
||||
@ -9663,11 +9776,10 @@ sub _beamGraphic {
|
||||
|
||||
my $ii = 0;
|
||||
|
||||
for my $i (0..($maxhours*2)-1) { # gleiche Bedingung wie oben
|
||||
next if (!$show_night && defined($hfcg->{$i}{weather})
|
||||
&& ($hfcg->{$i}{weather} > 99)
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2});
|
||||
for my $i (0..($maxhours * 2) - 1) { # gleiche Bedingung wie oben
|
||||
next if(!$show_night && $hfcg->{$i}{weather} > 99
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2});
|
||||
$ii++;
|
||||
last if ($ii > $maxhours);
|
||||
|
||||
@ -9768,7 +9880,7 @@ sub _beamGraphic {
|
||||
$ret .="<td style='text-align: center; padding-left:1px; padding-right:1px; margin:0px; vertical-align:bottom; padding-top:0px'>\n";
|
||||
|
||||
if ($lotype eq 'single') {
|
||||
$val = formatVal6($hfcg->{$i}{beam1},$kw,$hfcg->{$i}{weather});
|
||||
$val = formatVal6 ($hfcg->{$i}{beam1}, $kw, $hfcg->{$i}{weather});
|
||||
|
||||
$ret .="<table width='100%' height='100%'>"; # mit width=100% etwas bessere Füllung der Balken
|
||||
$ret .="<tr class='$htr{$m}{cl}' style='height:".$he."px'>";
|
||||
@ -9793,32 +9905,32 @@ sub _beamGraphic {
|
||||
|
||||
if ($lotype eq 'double') {
|
||||
my ($color1, $color2, $style1, $style2, $v);
|
||||
my $style = "style='padding-bottom:0px; padding-top:1px; vertical-align:top; margin-left:auto; margin-right:auto;";
|
||||
my $style = "style='padding-bottom:0px; padding-top:1px; vertical-align:top; margin-left:auto; margin-right:auto;";
|
||||
|
||||
$ret .="<table width='100%' height='100%'>\n"; # mit width=100% etwas bessere Füllung der Balken
|
||||
# der Freiraum oben kann beim größten Balken ganz entfallen
|
||||
$ret .="<tr class='$htr{$m}{cl}' style='height:".$he."px'><td class='solarfc'></td></tr>" if ($he);
|
||||
$ret .="<tr class='$htr{$m}{cl}' style='height:".$he."px'><td class='solarfc'></td></tr>" if($he);
|
||||
|
||||
if($hfcg->{$i}{beam1} > $hfcg->{$i}{beam2}) { # wer ist oben, Beam2 oder Beam1 ? Wert und Farbe für Zone 2 & 3 vorbesetzen
|
||||
$val = formatVal6($hfcg->{$i}{beam1},$kw,$hfcg->{$i}{weather});
|
||||
if ($hfcg->{$i}{beam1} > $hfcg->{$i}{beam2}) { # wer ist oben, Beam2 oder Beam1 ? Wert und Farbe für Zone 2 & 3 vorbesetzen
|
||||
$val = formatVal6 ($hfcg->{$i}{beam1}, $kw, $hfcg->{$i}{weather});
|
||||
$color1 = $colorb1;
|
||||
$style1 = $style." background-color:#$color1; color:#$fcolor1;'";
|
||||
|
||||
if ($z3) { # die Zuweisung können wir uns sparen wenn Zone 3 nachher eh nicht ausgegeben wird
|
||||
$v = formatVal6($hfcg->{$i}{beam2},$kw,$hfcg->{$i}{weather});
|
||||
$v = formatVal6 ($hfcg->{$i}{beam2}, $kw, $hfcg->{$i}{weather});
|
||||
$color2 = $colorb2;
|
||||
$style2 = $style." background-color:#$color2; color:#$fcolor2;'";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$val = formatVal6($hfcg->{$i}{beam2},$kw,$hfcg->{$i}{weather});
|
||||
$color1 = $colorb2;
|
||||
$style1 = $style." background-color:#$color1; color:#$fcolor2;'";
|
||||
$val = formatVal6 ($hfcg->{$i}{beam2}, $kw, $hfcg->{$i}{weather});
|
||||
$color1 = $colorb2;
|
||||
$style1 = $style." background-color:#$color1; color:#$fcolor2;'";
|
||||
|
||||
if ($z3) {
|
||||
$v = formatVal6($hfcg->{$i}{beam1},$kw,$hfcg->{$i}{weather});
|
||||
$color2 = $colorb1;
|
||||
$style2 = $style." background-color:#$color2; color:#$fcolor1;'";
|
||||
$v = formatVal6 ($hfcg->{$i}{beam1}, $kw, $hfcg->{$i}{weather});
|
||||
$color2 = $colorb1;
|
||||
$style2 = $style." background-color:#$color2; color:#$fcolor1;'";
|
||||
}
|
||||
}
|
||||
|
||||
@ -9841,7 +9953,7 @@ sub _beamGraphic {
|
||||
my $style = "style='padding-bottom:0px; padding-top:1px; vertical-align:top; margin-left:auto; margin-right:auto;";
|
||||
$ret .= "<table width='100%' border='0'>\n"; # Tipp : das nachfolgende border=0 auf 1 setzen hilft sehr Ausgabefehler zu endecken
|
||||
|
||||
$val = ($hfcg->{$i}{diff} > 0) ? formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}) : '';
|
||||
$val = ($hfcg->{$i}{diff} > 0) ? formatVal6 ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather}) : '';
|
||||
$val = ' 0 ' if ($hfcg->{$i}{diff} == 0); # Sonderfall , hier wird die 0 gebraucht !
|
||||
|
||||
if ($val) {
|
||||
@ -9875,14 +9987,14 @@ sub _beamGraphic {
|
||||
}
|
||||
|
||||
if($z4) { # kann entfallen wenn auch z3 0 ist
|
||||
$val = ($hfcg->{$i}{diff} < 0) ? formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather}) : ' ';
|
||||
$val = ($hfcg->{$i}{diff} < 0) ? formatVal6 ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather}) : ' ';
|
||||
$ret .= "<tr class='$htr{$m}{cl}' style='height:".$z4."px'>";
|
||||
$ret .= "<td class='solarfc' style='vertical-align:top'>".$val."</td></tr>";
|
||||
}
|
||||
}
|
||||
|
||||
if ($show_diff eq 'bottom') { # zusätzliche diff Anzeige
|
||||
$val = formatVal6($hfcg->{$i}{diff},$kw,$hfcg->{$i}{weather});
|
||||
$val = formatVal6 ($hfcg->{$i}{diff}, $kw, $hfcg->{$i}{weather});
|
||||
$val = ($hfcg->{$i}{diff} < 0) ? '<b>'.$val.'<b/>' : ($val > 0 ) ? '+'.$val : $val if ($val ne ' '); # negative Zahlen in Fettschrift, 0 aber ohne +
|
||||
$ret .= "<tr class='$htr{$m}{cl}'><td class='solarfc' style='vertical-align:middle; text-align:center;'>$val</td></tr>";
|
||||
}
|
||||
@ -9926,53 +10038,50 @@ sub __weatherOnBeam {
|
||||
|
||||
return $ret if(!$weather);
|
||||
|
||||
my $m = $paref->{modulo} % 2;
|
||||
my $m = $paref->{modulo} % 2;
|
||||
my $ii = 0;
|
||||
|
||||
$ret .= "<tr class='$htr{$m}{cl}'><td class='solarfc'></td>"; # freier Platz am Anfang
|
||||
|
||||
my $ii;
|
||||
for my $i (0..($maxhours*2)-1) {
|
||||
last if (!exists($hfcg->{$i}{weather}));
|
||||
next if (!$show_night && defined($hfcg->{$i}{weather})
|
||||
&& ($hfcg->{$i}{weather} > 99)
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2});
|
||||
for my $i (0..($maxhours * 2) - 1) {
|
||||
last if (!exists ($hfcg->{$i}{weather}));
|
||||
|
||||
$hfcg->{$i}{weather} = 999 if(!defined $hfcg->{$i}{weather});
|
||||
my $wcc = $hfcg->{$i}{wcc} // '-'; # Bewölkungsgrad ergänzen
|
||||
|
||||
debugLog ($paref, 'graphic', "weather id beam number >$i< (start hour $hfcg->{$i}{time_str}): wid $hfcg->{$i}{weather} / wcc $wcc") if($ii < $maxhours);
|
||||
|
||||
if (!$show_night && $hfcg->{$i}{weather} > 99
|
||||
&& !$hfcg->{$i}{beam1}
|
||||
&& !$hfcg->{$i}{beam2}) {
|
||||
|
||||
debugLog ($paref, 'graphic', "weather id >$i< don't show night condition ... is skipped") if($ii < $maxhours);
|
||||
next;
|
||||
};
|
||||
# Lässt Nachticons aber noch durch wenn es einen Wert gibt , ToDo : klären ob die Nacht richtig gesetzt wurde
|
||||
$ii++; # wieviele Stunden Icons haben wir bisher beechnet ?
|
||||
last if ($ii > $maxhours);
|
||||
# ToDo : weather_icon sollte im Fehlerfall Title mit der ID besetzen um in FHEMWEB sofort die ID sehen zu können
|
||||
if (exists($hfcg->{$i}{weather}) && defined($hfcg->{$i}{weather})) {
|
||||
my ($icon_name, $title) = $hfcg->{$i}{weather} > 100 ?
|
||||
weather_icon ($name, $lang, $hfcg->{$i}{weather}-100) :
|
||||
weather_icon ($name, $lang, $hfcg->{$i}{weather});
|
||||
last if($ii > $maxhours);
|
||||
# ToDo : weather_icon sollte im Fehlerfall Title mit der ID besetzen um in FHEMWEB sofort die ID sehen zu können
|
||||
my ($icon_name, $title) = $hfcg->{$i}{weather} > 100 ?
|
||||
weather_icon ($name, $lang, $hfcg->{$i}{weather}-100) :
|
||||
weather_icon ($name, $lang, $hfcg->{$i}{weather});
|
||||
|
||||
my $wcc = $hfcg->{$i}{wcc} // "-"; # Bewölkungsgrad ergänzen
|
||||
$wcc += 0 if(isNumeric ($wcc)); # Javascript Fehler vermeiden: https://forum.fhem.de/index.php/topic,117864.msg1233661.html#msg1233661
|
||||
$title .= ': '.$wcc;
|
||||
|
||||
if(isNumeric ($wcc)) { # Javascript Fehler vermeiden: https://forum.fhem.de/index.php/topic,117864.msg1233661.html#msg1233661
|
||||
$wcc += 0;
|
||||
}
|
||||
|
||||
$title .= ': '.$wcc;
|
||||
|
||||
if($icon_name eq 'unknown') {
|
||||
debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer");
|
||||
}
|
||||
|
||||
$icon_name .= $hfcg->{$i}{weather} < 100 ? '@'.$colorw : '@'.$colorwn;
|
||||
my $val = FW_makeImage($icon_name) // q{};
|
||||
|
||||
if ($val eq $icon_name) { # passendes Icon beim User nicht vorhanden ! ( attr web iconPath falsch/prüfen/update ? )
|
||||
$val = '<b>???<b/>';
|
||||
|
||||
debugLog ($paref, "graphic", qq{the icon "$weather_ids{$hfcg->{$i}{weather}}{icon}" not found. Please check attribute "iconPath" of your FHEMWEB instance and/or update your FHEM software});
|
||||
}
|
||||
|
||||
$ret .= "<td title='$title' class='solarfc' width='$width' style='margin:1px; vertical-align:middle align:center; padding-bottom:1px;'>$val</td>";
|
||||
if ($icon_name eq 'unknown') {
|
||||
debugLog ($paref, "graphic", "unknown weather id: ".$hfcg->{$i}{weather}.", please inform the maintainer");
|
||||
}
|
||||
else { # mit $hfcg->{$i}{weather} = undef kann man unten leicht feststellen ob für diese Spalte bereits ein Icon ausgegeben wurde oder nicht
|
||||
$ret .= "<td></td>";
|
||||
$hfcg->{$i}{weather} = undef; # ToDo : prüfen ob noch nötig
|
||||
|
||||
$icon_name .= $hfcg->{$i}{weather} < 100 ? '@'.$colorw : '@'.$colorwn;
|
||||
my $val = FW_makeImage ($icon_name) // q{};
|
||||
|
||||
if ($val =~ /title="$icon_name"/xs) { # passendes Icon beim User nicht vorhanden ! ( attr web iconPath falsch/prüfen/update ? )
|
||||
$val = '<b>???<b/>';
|
||||
debugLog ($paref, "graphic", qq{ERROR - the icon "$weather_ids{$hfcg->{$i}{weather}}{icon}.svg" not found. Please check attribute "iconPath" of your FHEMWEB instance and/or update your FHEM software});
|
||||
}
|
||||
|
||||
$ret .= "<td title='$title' class='solarfc' width='$width' style='margin:1px; vertical-align:middle align:center; padding-bottom:1px;'>$val</td>";
|
||||
}
|
||||
|
||||
$ret .= "<td class='solarfc'></td></tr>"; # freier Platz am Ende der Icon Zeile
|
||||
@ -10391,23 +10500,26 @@ return $ret;
|
||||
#
|
||||
###############################################################################
|
||||
sub formatVal6 {
|
||||
my ($v,$kw,$w) = @_;
|
||||
my $n = ' '; # positive Zahl
|
||||
my $v = shift;
|
||||
my $kw = shift;
|
||||
my $w = shift;
|
||||
|
||||
my $n = ' '; # positive Zahl
|
||||
|
||||
if($v < 0) {
|
||||
if ($v < 0) {
|
||||
$n = '-'; # negatives Vorzeichen merken
|
||||
$v = abs($v);
|
||||
}
|
||||
|
||||
if($kw eq 'kWh') { # bei Anzeige in kWh muss weniger aufgefüllt werden
|
||||
$v = sprintf "%.1f",($v/1000);
|
||||
if ($kw eq 'kWh') { # bei Anzeige in kWh muss weniger aufgefüllt werden
|
||||
$v = sprintf "%.1f",($v / 1000);
|
||||
$v += 0; # keine 0.0 oder 6.0 etc
|
||||
|
||||
return ($n eq '-') ? ($v*-1) : $v if defined($w) ;
|
||||
return ($n eq '-') ? ($v * -1) : $v if(defined $w);
|
||||
|
||||
my $t = $v - int($v); # Nachkommstelle ?
|
||||
|
||||
if(!$t) { # glatte Zahl ohne Nachkommastelle
|
||||
if (!$t) { # glatte Zahl ohne Nachkommastelle
|
||||
if(!$v) {
|
||||
return ' '; # 0 nicht anzeigen, passt eigentlich immer bis auf einen Fall im Typ diff
|
||||
}
|
||||
@ -10428,7 +10540,7 @@ sub formatVal6 {
|
||||
}
|
||||
}
|
||||
|
||||
return ($n eq '-') ? ($v*-1) : $v if defined($w);
|
||||
return ($n eq '-') ? ($v * -1) : $v if(defined $w);
|
||||
|
||||
# Werte bleiben in Watt
|
||||
if (!$v) { return ' '; } ## no critic "Cascading" # keine Anzeige bei Null
|
||||
@ -10454,7 +10566,7 @@ sub weather_icon {
|
||||
return $weather_ids{$id}{icon}, encode("utf8", $weather_ids{$id}{$txt});
|
||||
}
|
||||
|
||||
return 'unknown','';
|
||||
return ('unknown','');
|
||||
}
|
||||
|
||||
################################################################
|
||||
@ -10506,7 +10618,7 @@ return ($badev, $a ,$h);
|
||||
|
||||
################################################################
|
||||
# Korrekturen und Qualität berechnen / speichern
|
||||
# sowie AI Instanzen hinzufügen
|
||||
# sowie AI Quellen Daten hinzufügen
|
||||
################################################################
|
||||
sub calcValueImproves {
|
||||
my $paref = shift;
|
||||
@ -10551,7 +10663,7 @@ sub calcValueImproves {
|
||||
|
||||
_calcCaQcomplex ($paref); # Korrekturberechnung mit Bewölkung duchführen/speichern
|
||||
_calcCaQsimple ($paref); # einfache Korrekturberechnung duchführen/speichern
|
||||
_addHourAiRawdata ($paref); # AI Instanz hinzufügen
|
||||
_addHourAiRawdata ($paref); # AI Raw Data hinzufügen
|
||||
|
||||
delete $paref->{h};
|
||||
}
|
||||
@ -10722,7 +10834,7 @@ return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# AI Instanz für die abgeschlossene Stunde hinzufügen
|
||||
# AI Daten für die abgeschlossene Stunde hinzufügen
|
||||
################################################################
|
||||
sub _addHourAiRawdata {
|
||||
my $paref = shift;
|
||||
@ -10737,7 +10849,7 @@ sub _addHourAiRawdata {
|
||||
|
||||
debugLog ($paref, 'aiProcess', "start add AI raw data for hour: $h");
|
||||
|
||||
$paref->{ood} = 1;
|
||||
$paref->{ood} = 1; # Only One Day
|
||||
$paref->{rho} = $rho;
|
||||
|
||||
aiAddRawData ($paref); # Raw Daten für AI hinzufügen und sichern
|
||||
@ -14429,6 +14541,22 @@ to ensure that the system configuration is correct.
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-set-consumerNewPlanning"></a>
|
||||
<li><b>consumerNewPlanning <Consumer number> </b> <br><br>
|
||||
|
||||
The existing planning of the specified consumer is deleted. <br>
|
||||
The new planning is carried out immediately, taking into account the parameters set in the consumerXX attribute.
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
set <name> consumerNewPlanning 01 <br>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-set-consumerImmediatePlanning"></a>
|
||||
@ -15272,7 +15400,7 @@ to ensure that the system configuration is correct.
|
||||
<a id="SolarForecast-get-valDecTree"></a>
|
||||
<li><b>valDecTree </b> <br><br>
|
||||
|
||||
If AI support is activated in the SolarForecast Device, various AI-relevant data can be displayed:
|
||||
If AI support is activated in the SolarForecast Device, various AI-relevant data can be displayed :
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
@ -15962,7 +16090,7 @@ to ensure that the system configuration is correct.
|
||||
|
||||
<a id="SolarForecast-attr-graphicHeaderOwnspec"></a>
|
||||
<li><b>graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ... </b><br>
|
||||
Display of any reading values of the device. <br>
|
||||
Display of any readings, set commands and attributes of the device in the graphic header. <br>
|
||||
The values to be displayed are separated by spaces.
|
||||
Four values (fields) are displayed per line. <br>
|
||||
The input can be made in multiple lines. Values with the units "Wh" or "kWh" are converted according to the
|
||||
@ -15992,6 +16120,17 @@ to ensure that the system configuration is correct.
|
||||
<tr><td> </td><td>#Battery </td></tr>
|
||||
<tr><td> </td><td>in&nbsp;today:statistic_todayBatIn </td></tr>
|
||||
<tr><td> </td><td>out&nbsp;today:statistic_todayBatOut </td></tr>
|
||||
<tr><td> </td><td>: </td></tr>
|
||||
<tr><td> </td><td>: </td></tr>
|
||||
<tr><td> </td><td>#Settings </td></tr>
|
||||
<tr><td> </td><td>Autocorrection:pvCorrectionFactor_Auto : : : </td></tr>
|
||||
<tr><td> </td><td>Consumer<br>Replanning:consumerNewPlanning : : : </td></tr>
|
||||
<tr><td> </td><td>Consumer<br>Quickstart:consumerImmediatePlanning : : : </td></tr>
|
||||
<tr><td> </td><td>Weather:graphicShowWeather : : : </td></tr>
|
||||
<tr><td> </td><td>History:graphicHistoryHour : : : </td></tr>
|
||||
<tr><td> </td><td>GraphicSize:flowGraphicSize : : : </td></tr>
|
||||
<tr><td> </td><td>ShowNight:graphicShowNight : : : </td></tr>
|
||||
<tr><td> </td><td>Debug:ctrlDebug : : : </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
</li>
|
||||
@ -16274,6 +16413,22 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-set-consumerNewPlanning"></a>
|
||||
<li><b>consumerNewPlanning <Verbrauchernummer> </b> <br><br>
|
||||
|
||||
Es wird die vorhandene Planung des angegebenen Verbrauchers gelöscht. <br>
|
||||
Die Neuplanung wird unter Berücksichtigung der im consumerXX Attribut gesetzten Parameter sofort vorgenommen.
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
<b>Beispiel: </b> <br>
|
||||
set <name> consumerNewPlanning 01 <br>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<a id="SolarForecast-set-consumerImmediatePlanning"></a>
|
||||
<li><b>consumerImmediatePlanning <Verbrauchernummer> </b> <br><br>
|
||||
@ -17119,7 +17274,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<a id="SolarForecast-get-valDecTree"></a>
|
||||
<li><b>valDecTree </b> <br><br>
|
||||
|
||||
Ist der KI Support im SolarForecast Device aktiviert, können verschiedene KI relevante Daten angezeigt werden:
|
||||
Ist der KI Support im SolarForecast Device aktiviert, können verschiedene KI relevante Daten angezeigt werden :
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
@ -17808,7 +17963,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
|
||||
<a id="SolarForecast-attr-graphicHeaderOwnspec"></a>
|
||||
<li><b>graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ... </b><br>
|
||||
Anzeige beliebiger Readingswerte des Devices. <br>
|
||||
Anzeige beliebiger Readings, Set-Kommandos und Attribute des Devices im Grafikkopf. <br>
|
||||
Die anzuzeigenden Werte werden durch Leerzeichen getrennt.
|
||||
Es werden vier Werte (Felder) pro Zeile dargestellt. <br>
|
||||
Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten "Wh" bzw. "kWh" werden entsprechend der Einstellung
|
||||
@ -17838,6 +17993,17 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
||||
<tr><td> </td><td>#Batterie </td></tr>
|
||||
<tr><td> </td><td>in&nbsp;heute:statistic_todayBatIn </td></tr>
|
||||
<tr><td> </td><td>out&nbsp;heute:statistic_todayBatOut </td></tr>
|
||||
<tr><td> </td><td>: </td></tr>
|
||||
<tr><td> </td><td>: </td></tr>
|
||||
<tr><td> </td><td>#Settings </td></tr>
|
||||
<tr><td> </td><td>Autokorrektur:pvCorrectionFactor_Auto : : : </td></tr>
|
||||
<tr><td> </td><td>Consumer<br>Neuplanung:consumerNewPlanning : : : </td></tr>
|
||||
<tr><td> </td><td>Consumer<br>Sofortstart:consumerImmediatePlanning : : : </td></tr>
|
||||
<tr><td> </td><td>Wetter:graphicShowWeather : : : </td></tr>
|
||||
<tr><td> </td><td>History:graphicHistoryHour : : : </td></tr>
|
||||
<tr><td> </td><td>GraphicSize:flowGraphicSize : : : </td></tr>
|
||||
<tr><td> </td><td>ShowNight:graphicShowNight : : : </td></tr>
|
||||
<tr><td> </td><td>Debug:ctrlDebug : : : </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
</li>
|
||||
|
Loading…
x
Reference in New Issue
Block a user