2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-15 22:26:04 +00:00

76_SolarForecast: graphicHeaderOwnspec: show readings of other devs, new set/reset batteryTrigger command

git-svn-id: https://svn.fhem.de/fhem/trunk@28204 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2023-11-25 15:07:53 +00:00
parent 102c440905
commit 4337a1e3b0
3 changed files with 348 additions and 261 deletions

View File

@ -1,5 +1,7 @@
# 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: graphicHeaderOwnspec: show readings of other devs
new set/reset batteryTrigger command
- bugfix: 98_CDCOpenData: warning Net::FTP bei Fhem Start - bugfix: 98_CDCOpenData: warning Net::FTP bei Fhem Start
- bugfix: 72_FRITZBOX set <name> lockLandevice für FritzOS >= 7.50 - bugfix: 72_FRITZBOX set <name> lockLandevice für FritzOS >= 7.50
- feature: 72_FRITZBOX set <name> lockLandevice Parameter rt (realtime) - feature: 72_FRITZBOX set <name> lockLandevice Parameter rt (realtime)

View File

@ -150,6 +150,7 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.2.0" => "25.11.2023 graphicHeaderOwnspec: show readings of other devs by <reaging>@<dev>, Set/reset batteryTrigger ",
"1.1.3" => "24.11.2023 rename reset arguments according possible adjustable textField width ", "1.1.3" => "24.11.2023 rename reset arguments according possible adjustable textField width ",
"1.1.2" => "20.11.2023 ctrlDebug Adjustment of column width, must have new fhemweb.js Forum:#135850 ", "1.1.2" => "20.11.2023 ctrlDebug Adjustment of column width, must have new fhemweb.js Forum:#135850 ",
"1.1.1" => "19.11.2023 graphicHeaderOwnspec: fix ignoring the last element of allsets/allattr ", "1.1.1" => "19.11.2023 graphicHeaderOwnspec: fix ignoring the last element of allsets/allattr ",
@ -557,9 +558,10 @@ my %hset = ( # Ha
currentInverterDev => { fn => \&_setinverterDevice }, currentInverterDev => { fn => \&_setinverterDevice },
currentMeterDev => { fn => \&_setmeterDevice }, currentMeterDev => { fn => \&_setmeterDevice },
currentBatteryDev => { fn => \&_setbatteryDevice }, currentBatteryDev => { fn => \&_setbatteryDevice },
energyH4Trigger => { fn => \&_setenergyH4Trigger }, energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration }, plantConfiguration => { fn => \&_setplantConfiguration },
powerTrigger => { fn => \&_setpowerTrigger }, batteryTrigger => { fn => \&_setTrigger },
powerTrigger => { fn => \&_setTrigger },
pvCorrectionFactor_05 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_05 => { fn => \&_setpvCorrectionFactor },
pvCorrectionFactor_06 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_06 => { fn => \&_setpvCorrectionFactor },
pvCorrectionFactor_07 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_07 => { fn => \&_setpvCorrectionFactor },
@ -1275,6 +1277,7 @@ sub Set {
my ($fcd,$ind,$med,$cf,$sp,$coms) = ('','','','','',''); my ($fcd,$ind,$med,$cf,$sp,$coms) = ('','','','','','');
my @re = qw( aiData my @re = qw( aiData
batteryTriggerSet
consumerMaster consumerMaster
consumerPlanning consumerPlanning
consumption consumption
@ -1360,6 +1363,12 @@ sub Set {
if ($ipai) { if ($ipai) {
$setlist .= "aiDecTree:addInstances,addRawData,train "; $setlist .= "aiDecTree:addInstances,addRawData,train ";
} }
## Batterie spezifische Setter
################################
if (isBatteryUsed ($name)) {
$setlist .= "batteryTrigger:textField-long ";
}
my $params = { my $params = {
hash => $hash, hash => $hash,
@ -1709,7 +1718,7 @@ sub _setinverterStrings { ## no critic "not used"
} }
readingsSingleUpdate ($hash, "inverterStrings", $prop, 1); readingsSingleUpdate ($hash, "inverterStrings", $prop, 1);
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett
@ -1814,9 +1823,9 @@ return;
} }
################################################################ ################################################################
# Setter powerTrigger # Setter powerTrigger / batterytrigger / energyH4Trigger
################################################################ ################################################################
sub _setpowerTrigger { ## no critic "not used" sub _setTrigger { ## no critic "not used"
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
@ -1839,40 +1848,20 @@ sub _setpowerTrigger { ## no critic "not used"
} }
} }
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben if ($opt eq 'powerTrigger') {
readingsSingleUpdate ($hash, "powerTrigger", $arg, 1); deleteReadingspec ($hash, 'powerTrigger.*');
readingsSingleUpdate ($hash, 'powerTrigger', $arg, 1);
return;
}
################################################################
# Setter energyH4Trigger
################################################################
sub _setenergyH4Trigger { ## no critic "not used"
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
my $opt = $paref->{opt};
my $arg = $paref->{arg};
if(!$arg) {
return qq{The command "$opt" needs an argument !};
} }
elsif ($opt eq 'batteryTrigger') {
my ($a,$h) = parseParams ($arg); deleteReadingspec ($hash, 'batteryTrigger.*');
readingsSingleUpdate ($hash, 'batteryTrigger', $arg, 1);
if(!$h) { }
return qq{The syntax of "$opt" is not correct. Please consider the commandref.}; elsif ($opt eq 'energyH4Trigger') {
deleteReadingspec ($hash, 'energyH4Trigger.*');
readingsSingleUpdate ($hash, 'energyH4Trigger', $arg, 1);
} }
for my $key (keys %{$h}) { writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
if($key !~ /^[0-9]+(?:on|off)$/x || $h->{$key} !~ /^[0-9]+$/x) {
return qq{The key "$key" is invalid. Please consider the commandref.};
}
}
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
readingsSingleUpdate ($hash, "energyH4Trigger", $arg, 1);
return; return;
} }
@ -2257,6 +2246,12 @@ sub _setreset { ## no critic "not used"
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
return; return;
} }
if ($prop eq 'batteryTriggerSet') {
deleteReadingspec ($hash, "batteryTrigger.*");
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name);
return;
}
if ($prop eq 'energyH4TriggerSet') { if ($prop eq 'energyH4TriggerSet') {
deleteReadingspec ($hash, "energyH4Trigger.*"); deleteReadingspec ($hash, "energyH4Trigger.*");
@ -2310,6 +2305,7 @@ sub _setreset { ## no critic "not used"
readingsDelete ($hash, "Current_PowerBatIn"); readingsDelete ($hash, "Current_PowerBatIn");
readingsDelete ($hash, "Current_PowerBatOut"); readingsDelete ($hash, "Current_PowerBatOut");
readingsDelete ($hash, "Current_BatCharge"); readingsDelete ($hash, "Current_BatCharge");
undef @{$data{$type}{$name}{current}{socslidereg}};
delete $data{$type}{$name}{circular}{'99'}{initdaybatintot}; delete $data{$type}{$name}{circular}{'99'}{initdaybatintot};
delete $data{$type}{$name}{circular}{'99'}{initdaybatouttot}; delete $data{$type}{$name}{circular}{'99'}{initdaybatouttot};
delete $data{$type}{$name}{circular}{'99'}{batintot}; delete $data{$type}{$name}{circular}{'99'}{batintot};
@ -2322,6 +2318,7 @@ sub _setreset { ## no critic "not used"
} }
if ($prop eq 'currentInverterSet') { if ($prop eq 'currentInverterSet') {
undef @{$data{$type}{$name}{current}{genslidereg}};
readingsDelete ($hash, "Current_PV"); readingsDelete ($hash, "Current_PV");
deleteReadingspec ($hash, ".*_PVreal" ); deleteReadingspec ($hash, ".*_PVreal" );
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
@ -5973,7 +5970,7 @@ sub _transferBatteryValues {
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $day = $paref->{day}; my $day = $paref->{day};
my ($badev,$a,$h) = useBattery ($name); my ($badev,$a,$h) = isBatteryUsed ($name);
return if(!$badev); return if(!$badev);
my $type = $paref->{type}; my $type = $paref->{type};
@ -6107,7 +6104,7 @@ sub _transferBatteryValues {
setPVhistory ($paref); setPVhistory ($paref);
delete $paref->{histname}; delete $paref->{histname};
###### ######
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatIn', $batinthishour.' Wh'); storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatIn', $batinthishour.' Wh');
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatOut', $batoutthishour.' Wh'); storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatOut', $batoutthishour.' Wh');
@ -6118,6 +6115,9 @@ sub _transferBatteryValues {
$data{$type}{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung $data{$type}{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung
$data{$type}{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung $data{$type}{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung
$data{$type}{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung $data{$type}{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung
push @{$data{$type}{$name}{current}{socslidereg}}, $soc; # Schieberegister Batterie SOC
limitArray ($data{$type}{$name}{current}{socslidereg}, $defslidenum);
return; return;
} }
@ -7492,7 +7492,7 @@ sub ___enableSwitchByBatPrioCharge {
my $ena = 1; my $ena = 1;
my $pcb = AttrVal ($name, 'affectBatteryPreferredCharge', 0); # Vorrangladung Batterie zu X% my $pcb = AttrVal ($name, 'affectBatteryPreferredCharge', 0); # Vorrangladung Batterie zu X%
my ($badev) = useBattery ($name); my ($badev) = isBatteryUsed ($name);
return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert
@ -7668,38 +7668,35 @@ sub _evaluateThresholds {
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $pt = ReadingsVal($name, "powerTrigger", ""); my $bt = ReadingsVal($name, 'batteryTrigger', '');
my $eh4t = ReadingsVal($name, "energyH4Trigger", ""); my $pt = ReadingsVal($name, 'powerTrigger', '');
my $eh4t = ReadingsVal($name, 'energyH4Trigger', '');
if ($bt) {
$paref->{cobj} = 'socslidereg';
$paref->{tname} = 'batteryTrigger';
$paref->{tholds} = $bt;
__evaluateArray ($paref);
}
if ($pt) { if ($pt) {
my $aaref = CurrentVal ($hash, "genslidereg", ""); $paref->{cobj} = 'genslidereg';
my @aa = (); $paref->{tname} = 'powerTrigger';
@aa = @{$aaref} if (ref $aaref eq "ARRAY"); $paref->{tholds} = $pt;
if (scalar @aa >= $defslidenum) { __evaluateArray ($paref);
$paref->{taref} = \@aa;
$paref->{tname} = "powerTrigger";
$paref->{tholds} = $pt;
__evaluateArray ($paref);
}
} }
if ($eh4t) { if ($eh4t) {
my $aaref = CurrentVal ($hash, "h4fcslidereg", ""); $paref->{cobj} = 'h4fcslidereg';
my @aa = (); $paref->{tname} = 'energyH4Trigger';
@aa = @{$aaref} if (ref $aaref eq "ARRAY"); $paref->{tholds} = $eh4t;
__evaluateArray ($paref);
}
if (scalar @aa >= $defslidenum) { delete $paref->{cobj};
$paref->{taref} = \@aa;
$paref->{tname} = "energyH4Trigger";
$paref->{tholds} = $eh4t;
__evaluateArray ($paref);
}
}
delete $paref->{taref};
delete $paref->{tname}; delete $paref->{tname};
delete $paref->{tholds}; delete $paref->{tholds};
@ -7711,14 +7708,22 @@ return;
################################################################ ################################################################
sub __evaluateArray { sub __evaluateArray {
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $taref = $paref->{taref}; # Referenz zum Threshold-Array my $cobj = $paref->{cobj}; # das CurrentVal Objekt, z.B. genslidereg
my $tname = $paref->{tname}; # Thresholdname, z.B. powerTrigger my $tname = $paref->{tname}; # Thresholdname, z.B. powerTrigger
my $tholds = $paref->{tholds}; # Triggervorgaben, z.B. aus Reading powerTrigger my $tholds = $paref->{tholds}; # Triggervorgaben, z.B. aus Reading powerTrigger
my $aaref = CurrentVal ($hash, $cobj, '');
my @aa = ();
@aa = @{$aaref} if (ref $aaref eq 'ARRAY');
return if(scalar @aa < $defslidenum);
my $gen1 = @$taref[0]; my $gen1 = @aa[0];
my $gen2 = @$taref[1]; my $gen2 = @aa[1];
my $gen3 = @$taref[2]; my $gen3 = @aa[2];
my ($a,$h) = parseParams ($tholds); my ($a,$h) = parseParams ($tholds);
@ -9138,8 +9143,8 @@ sub __createOwnSpec {
for (my $i = 1 ; $i <= $rows; $i++) { for (my $i = 1 ; $i <= $rows; $i++) {
my ($h, $v, $u); my ($h, $v, $u);
for (my $k = 0 ; $k < $vinr; $k++) { for (my $k = 0 ; $k < $vinr; $k++) {
($h->{$k}{label}, $h->{$k}{rdg}) = split ":", $vals[$col] if($vals[$col]); ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]);
$col++; $col++;
if (!$h->{$k}{label}) { if (!$h->{$k}{label}) {
@ -9147,23 +9152,31 @@ sub __createOwnSpec {
next; next;
} }
my $setcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allsets, 'set'); if ($h->{$k}{elm} !~ /@/xs) {
my $setcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allsets, 'set');
if ($setcmd) {
$v->{$k} = $setcmd; if ($setcmd) {
$u->{$k} = q{}; $v->{$k} = $setcmd;
next; $u->{$k} = q{};
next;
}
my $attrcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allattrs, 'attr');
if ($attrcmd) {
$v->{$k} = $attrcmd;
$u->{$k} = q{};
next;
}
} }
my $attrcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allattrs, 'attr'); my ($rdg, $dev) = split "@", $h->{$k}{elm};
$dev //= $name;
if ($attrcmd) { ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $rdg, '');
$v->{$k} = $attrcmd;
$u->{$k} = q{};
next;
}
($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($name, $h->{$k}{rdg}, ' '); $v->{$k} //= q{};
$u->{$k} //= q{};
next if(!$u->{$k}); next if(!$u->{$k});
@ -10605,21 +10618,6 @@ sub checkdwdattr {
return $err; return $err;
} }
################################################################
# ist Batterie installiert ?
# 1 - ja, 0 - nein
################################################################
sub useBattery {
my $name = shift;
my $badev = ReadingsVal($name, "currentBatteryDev", ""); # aktuelles Meter device für Batteriewerte
my ($a,$h) = parseParams ($badev);
$badev = $a->[0] // "";
return if(!$badev || !$defs{$badev});
return ($badev, $a ,$h);
}
################################################################ ################################################################
# Korrekturen und Qualität berechnen / speichern # Korrekturen und Qualität berechnen / speichern
# sowie AI Quellen Daten hinzufügen # sowie AI Quellen Daten hinzufügen
@ -10629,7 +10627,7 @@ sub calcValueImproves {
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $t = $paref->{t}; # aktuelle Unix-Zeit my $t = $paref->{t}; # aktuelle Unix-Zeit
my $idts = ReadingsTimestamp ($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice my $idts = ReadingsTimestamp ($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice
return if(!$idts); return if(!$idts);
@ -13435,6 +13433,22 @@ sub isConsRcmd {
return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0); return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0);
} }
################################################################
# ist Batterie installiert ?
# 1 - ja, 0 - nein
################################################################
sub isBatteryUsed {
my $name = shift;
my $badev = ReadingsVal($name, "currentBatteryDev", ""); # aktuelles Meter device für Batteriewerte
my ($a,$h) = parseParams ($badev);
$badev = $a->[0] // "";
return if(!$badev || !$defs{$badev});
return ($badev, $a ,$h);
}
################################################################ ################################################################
# ist Consumer $c unterbrechbar (1|2) oder nicht (0|3) # ist Consumer $c unterbrechbar (1|2) oder nicht (0|3)
################################################################ ################################################################
@ -14144,6 +14158,7 @@ return $def;
# aiaddistate - Add Instanz Status der KI # aiaddistate - Add Instanz Status der KI
# genslidereg - Schieberegister PV Erzeugung (Array) # genslidereg - Schieberegister PV Erzeugung (Array)
# h4fcslidereg - Schieberegister 4h PV Forecast (Array) # h4fcslidereg - Schieberegister 4h PV Forecast (Array)
# socslidereg - Schieberegister Batterie SOC (Array)
# consumption - aktueller Verbrauch (W) # consumption - aktueller Verbrauch (W)
# consumerdevs - alle registrierten Consumerdevices (Array) # consumerdevs - alle registrierten Consumerdevices (Array)
# gridconsumption - aktueller Netzbezug # gridconsumption - aktueller Netzbezug
@ -15054,6 +15069,7 @@ to ensure that the system configuration is correct.
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="20%"> <col width="80%"> </colgroup>
<tr><td> <b>aiData</b> </td><td>deletes an existing AI instance including all training data and reinitialises it </td></tr> <tr><td> <b>aiData</b> </td><td>deletes an existing AI instance including all training data and reinitialises it </td></tr>
<tr><td> <b>batteryTriggerSet</b> </td><td>deletes the trigger points of the battery storage </td></tr>
<tr><td> <b>consumerPlanning</b> </td><td>deletes the planning data of all registered consumers </td></tr> <tr><td> <b>consumerPlanning</b> </td><td>deletes the planning data of all registered consumers </td></tr>
<tr><td> </td><td>To delete the planning data of only one consumer, use: </td></tr> <tr><td> </td><td>To delete the planning data of only one consumer, use: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Consumer number&gt; </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Consumer number&gt; </ul> </td></tr>
@ -16415,6 +16431,27 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
</li> </li>
</ul> </ul>
<br> <br>
<ul>
<a id="SolarForecast-set-batteryTrigger"></a>
<li><b>batteryTrigger &lt;1on&gt;=&lt;Wert&gt; &lt;1off&gt;=&lt;Wert&gt; [&lt;2on&gt;=&lt;Wert&gt; &lt;2off&gt;=&lt;Wert&gt; ...] </b> <br><br>
Generiert Trigger bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SOC in %). <br>
Überschreiten die letzten drei SOC-Messungen eine definierte <b>Xon-Bedingung</b>, wird das Reading
<b>batteryTrigger_X = on</b> erstellt/gesetzt.
Unterschreiten die letzten drei SOC-Messungen eine definierte <b>Xoff-Bedingung</b>, wird das Reading
<b>batteryTrigger_X = off</b> erstellt/gesetzt. <br>
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise
definiert werden. <br>
<br>
<ul>
<b>Beispiel: </b> <br>
set &lt;name&gt; batteryTrigger 1on=30 1off=10 2on=70 2off=20 3on=15 4off=90<br>
</ul>
</li>
</ul>
<br>
<ul> <ul>
<a id="SolarForecast-set-consumerNewPlanning"></a> <a id="SolarForecast-set-consumerNewPlanning"></a>
@ -16929,6 +16966,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="20%"> <col width="80%"> </colgroup>
<tr><td> <b>aiData</b> </td><td>löscht eine vorhandene KI Instanz inklusive aller Trainingsdaten und initialisiert sie neu </td></tr> <tr><td> <b>aiData</b> </td><td>löscht eine vorhandene KI Instanz inklusive aller Trainingsdaten und initialisiert sie neu </td></tr>
<tr><td> <b>batteryTriggerSet</b> </td><td>löscht die Triggerpunkte des Batteriespeichers </td></tr>
<tr><td> <b>consumerPlanning</b> </td><td>löscht die Planungsdaten aller registrierten Verbraucher </td></tr> <tr><td> <b>consumerPlanning</b> </td><td>löscht die Planungsdaten aller registrierten Verbraucher </td></tr>
<tr><td> </td><td>Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man: </td></tr> <tr><td> </td><td>Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Verbrauchernummer&gt; </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Verbrauchernummer&gt; </ul> </td></tr>
@ -17964,8 +18002,9 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<br> <br>
<a id="SolarForecast-attr-graphicHeaderOwnspec"></a> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a>
<li><b>graphicHeaderOwnspec &lt;Label&gt;:&lt;Reading&gt; &lt;Label&gt;:&lt;Reading&gt; ... </b><br> <li><b>graphicHeaderOwnspec &lt;Label&gt;:&lt;Reading[@Device]&gt; &lt;Label&gt;:&lt;Reading[@Device]&gt; ... </b><br>
Anzeige beliebiger Readings, Set-Kommandos und Attribute des Devices im Grafikkopf. <br> Anzeige beliebiger Readings, Set-Kommandos und Attribute des SolarForecast Devices im Grafikkopf. <br>
Durch Angabe des optionalen [@Device] können Readings anderer Devices angezeigt werden. <br>
Die anzuzeigenden Werte werden durch Leerzeichen getrennt. Die anzuzeigenden Werte werden durch Leerzeichen getrennt.
Es werden vier Werte (Felder) pro Zeile dargestellt. <br> 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 Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten "Wh" bzw. "kWh" werden entsprechend der Einstellung
@ -17990,7 +18029,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td># </td></tr> <tr><td> </td><td># </td></tr>
<tr><td> </td><td>CO&amp;nbsp;bis&amp;nbsp;Sonnenuntergang:statistic_todayConForecastTillSunset </td></tr> <tr><td> </td><td>CO&amp;nbsp;bis&amp;nbsp;Sonnenuntergang:statistic_todayConForecastTillSunset </td></tr>
<tr><td> </td><td>PV&amp;nbsp;Übermorgen:statistic_dayAfterTomorrowPVforecast </td></tr> <tr><td> </td><td>PV&amp;nbsp;Übermorgen:statistic_dayAfterTomorrowPVforecast </td></tr>
<tr><td> </td><td>: </td></tr> <tr><td> </td><td>InverterRelay:gridrelay_status@MySTP_5000 </td></tr>
<tr><td> </td><td>: </td></tr> <tr><td> </td><td>: </td></tr>
<tr><td> </td><td>#Batterie </td></tr> <tr><td> </td><td>#Batterie </td></tr>
<tr><td> </td><td>in&amp;nbsp;heute:statistic_todayBatIn </td></tr> <tr><td> </td><td>in&amp;nbsp;heute:statistic_todayBatIn </td></tr>

View File

@ -126,6 +126,7 @@ BEGIN {
FW_room FW_room
FW_detail FW_detail
FW_widgetFallbackFn FW_widgetFallbackFn
FW_widgetOverride
FW_wname FW_wname
) )
); );
@ -149,6 +150,10 @@ BEGIN {
# Versions History intern # Versions History intern
my %vNotesIntern = ( my %vNotesIntern = (
"1.2.0" => "25.11.2023 graphicHeaderOwnspec: show readings of other devs by <reaging>@<dev>, Set/reset batteryTrigger ",
"1.1.3" => "24.11.2023 rename reset arguments according possible adjustable textField width ",
"1.1.2" => "20.11.2023 ctrlDebug Adjustment of column width, must have new fhemweb.js Forum:#135850 ",
"1.1.1" => "19.11.2023 graphicHeaderOwnspec: fix ignoring the last element of allsets/allattr ",
"1.1.0" => "14.11.2023 graphicHeaderOwnspec: possible add set/attr commands, new setter consumerNewPlanning ", "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.10" => "31.10.2023 fix warnings, edit comref ",
"1.0.9" => "29.10.2023 _aiGetSpread: set spread from 50 to 20 ", "1.0.9" => "29.10.2023 _aiGetSpread: set spread from 50 to 20 ",
@ -553,9 +558,10 @@ my %hset = ( # Ha
currentInverterDev => { fn => \&_setinverterDevice }, currentInverterDev => { fn => \&_setinverterDevice },
currentMeterDev => { fn => \&_setmeterDevice }, currentMeterDev => { fn => \&_setmeterDevice },
currentBatteryDev => { fn => \&_setbatteryDevice }, currentBatteryDev => { fn => \&_setbatteryDevice },
energyH4Trigger => { fn => \&_setenergyH4Trigger }, energyH4Trigger => { fn => \&_setTrigger },
plantConfiguration => { fn => \&_setplantConfiguration }, plantConfiguration => { fn => \&_setplantConfiguration },
powerTrigger => { fn => \&_setpowerTrigger }, batteryTrigger => { fn => \&_setTrigger },
powerTrigger => { fn => \&_setTrigger },
pvCorrectionFactor_05 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_05 => { fn => \&_setpvCorrectionFactor },
pvCorrectionFactor_06 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_06 => { fn => \&_setpvCorrectionFactor },
pvCorrectionFactor_07 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_07 => { fn => \&_setpvCorrectionFactor },
@ -1032,7 +1038,7 @@ sub Initialize {
"ctrlAutoRefresh:selectnumbers,120,0.2,1800,0,log10 ". "ctrlAutoRefresh:selectnumbers,120,0.2,1800,0,log10 ".
"ctrlAutoRefreshFW:$fwd ". "ctrlAutoRefreshFW:$fwd ".
"ctrlConsRecommendReadings:multiple-strict,$allcs ". "ctrlConsRecommendReadings:multiple-strict,$allcs ".
"ctrlDebug:multiple-strict,$dm ". "ctrlDebug:multiple-strict,$dm,#14 ".
"ctrlGenPVdeviation:daily,continuously ". "ctrlGenPVdeviation:daily,continuously ".
"ctrlInterval ". "ctrlInterval ".
"ctrlLanguage:DE,EN ". "ctrlLanguage:DE,EN ".
@ -1064,7 +1070,7 @@ sub Initialize {
"graphicHeaderOwnspec:textField-long ". "graphicHeaderOwnspec:textField-long ".
"graphicHeaderDetail:multiple-strict,all,co,pv,own,status ". "graphicHeaderDetail:multiple-strict,all,co,pv,own,status ".
"graphicHeaderShow:1,0 ". "graphicHeaderShow:1,0 ".
"graphicHistoryHour:selectnumbers,0,1,23,0,lin ". "graphicHistoryHour:slider,0,1,23 ".
"graphicHourCount:slider,4,1,24 ". "graphicHourCount:slider,4,1,24 ".
"graphicHourStyle ". "graphicHourStyle ".
"graphicLayoutType:single,double,diff ". "graphicLayoutType:single,double,diff ".
@ -1271,17 +1277,17 @@ sub Set {
my ($fcd,$ind,$med,$cf,$sp,$coms) = ('','','','','',''); my ($fcd,$ind,$med,$cf,$sp,$coms) = ('','','','','','');
my @re = qw( aiData my @re = qw( aiData
batteryTriggerSet
consumerMaster consumerMaster
consumerPlanning consumerPlanning
consumption consumption
currentBatteryDev currentBatterySet
currentWeatherDev currentInverterSet
currentInverterDev currentMeterSet
currentMeterDev energyH4TriggerSet
energyH4Trigger inverterStringSet
inverterStrings moduleRoofTopSet
moduleRoofTops powerTriggerSet
powerTrigger
pvCorrection pvCorrection
roofIdentPair roofIdentPair
pvHistory pvHistory
@ -1357,6 +1363,12 @@ sub Set {
if ($ipai) { if ($ipai) {
$setlist .= "aiDecTree:addInstances,addRawData,train "; $setlist .= "aiDecTree:addInstances,addRawData,train ";
} }
## Batterie spezifische Setter
################################
if (isBatteryUsed ($name)) {
$setlist .= "batteryTrigger:textField-long ";
}
my $params = { my $params = {
hash => $hash, hash => $hash,
@ -1706,7 +1718,7 @@ sub _setinverterStrings { ## no critic "not used"
} }
readingsSingleUpdate ($hash, "inverterStrings", $prop, 1); readingsSingleUpdate ($hash, "inverterStrings", $prop, 1);
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett return if(_checkSetupNotComplete ($hash)); # keine Stringkonfiguration wenn Setup noch nicht komplett
@ -1811,9 +1823,9 @@ return;
} }
################################################################ ################################################################
# Setter powerTrigger # Setter powerTrigger / batterytrigger / energyH4Trigger
################################################################ ################################################################
sub _setpowerTrigger { ## no critic "not used" sub _setTrigger { ## no critic "not used"
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
@ -1836,40 +1848,20 @@ sub _setpowerTrigger { ## no critic "not used"
} }
} }
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben if ($opt eq 'powerTrigger') {
readingsSingleUpdate ($hash, "powerTrigger", $arg, 1); deleteReadingspec ($hash, 'powerTrigger.*');
readingsSingleUpdate ($hash, 'powerTrigger', $arg, 1);
return;
}
################################################################
# Setter energyH4Trigger
################################################################
sub _setenergyH4Trigger { ## no critic "not used"
my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name};
my $opt = $paref->{opt};
my $arg = $paref->{arg};
if(!$arg) {
return qq{The command "$opt" needs an argument !};
} }
elsif ($opt eq 'batteryTrigger') {
my ($a,$h) = parseParams ($arg); deleteReadingspec ($hash, 'batteryTrigger.*');
readingsSingleUpdate ($hash, 'batteryTrigger', $arg, 1);
if(!$h) { }
return qq{The syntax of "$opt" is not correct. Please consider the commandref.}; elsif ($opt eq 'energyH4Trigger') {
deleteReadingspec ($hash, 'energyH4Trigger.*');
readingsSingleUpdate ($hash, 'energyH4Trigger', $arg, 1);
} }
for my $key (keys %{$h}) { writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
if($key !~ /^[0-9]+(?:on|off)$/x || $h->{$key} !~ /^[0-9]+$/x) {
return qq{The key "$key" is invalid. Please consider the commandref.};
}
}
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
readingsSingleUpdate ($hash, "energyH4Trigger", $arg, 1);
return; return;
} }
@ -2249,21 +2241,27 @@ sub _setreset { ## no critic "not used"
return; return;
} }
if ($prop eq 'powerTrigger') { if ($prop eq 'powerTriggerSet') {
deleteReadingspec ($hash, "powerTrigger.*"); deleteReadingspec ($hash, "powerTrigger.*");
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
return;
}
if ($prop eq 'batteryTriggerSet') {
deleteReadingspec ($hash, "batteryTrigger.*");
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name);
return; return;
} }
if ($prop eq 'energyH4Trigger') { if ($prop eq 'energyH4TriggerSet') {
deleteReadingspec ($hash, "energyH4Trigger.*"); deleteReadingspec ($hash, "energyH4Trigger.*");
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name);
return; return;
} }
if ($prop eq 'moduleRoofTops') { if ($prop eq 'moduleRoofTopSet') {
deleteReadingspec ($hash, "moduleRoofTops"); deleteReadingspec ($hash, "moduleRoofTops");
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name);
return; return;
} }
@ -2285,7 +2283,7 @@ sub _setreset { ## no critic "not used"
return; return;
} }
if ($prop eq 'currentMeterDev') { if ($prop eq 'currentMeterSet') {
readingsDelete ($hash, "Current_GridConsumption"); readingsDelete ($hash, "Current_GridConsumption");
readingsDelete ($hash, "Current_GridFeedIn"); readingsDelete ($hash, "Current_GridFeedIn");
delete $data{$type}{$name}{circular}{'99'}{initdayfeedin}; delete $data{$type}{$name}{circular}{'99'}{initdayfeedin};
@ -2303,10 +2301,11 @@ sub _setreset { ## no critic "not used"
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
} }
if ($prop eq 'currentBatteryDev') { if ($prop eq 'currentBatterySet') {
readingsDelete ($hash, "Current_PowerBatIn"); readingsDelete ($hash, "Current_PowerBatIn");
readingsDelete ($hash, "Current_PowerBatOut"); readingsDelete ($hash, "Current_PowerBatOut");
readingsDelete ($hash, "Current_BatCharge"); readingsDelete ($hash, "Current_BatCharge");
undef @{$data{$type}{$name}{current}{socslidereg}};
delete $data{$type}{$name}{circular}{'99'}{initdaybatintot}; delete $data{$type}{$name}{circular}{'99'}{initdaybatintot};
delete $data{$type}{$name}{circular}{'99'}{initdaybatouttot}; delete $data{$type}{$name}{circular}{'99'}{initdaybatouttot};
delete $data{$type}{$name}{circular}{'99'}{batintot}; delete $data{$type}{$name}{circular}{'99'}{batintot};
@ -2318,7 +2317,8 @@ sub _setreset { ## no critic "not used"
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
} }
if ($prop eq 'currentInverterDev') { if ($prop eq 'currentInverterSet') {
undef @{$data{$type}{$name}{current}{genslidereg}};
readingsDelete ($hash, "Current_PV"); readingsDelete ($hash, "Current_PV");
deleteReadingspec ($hash, ".*_PVreal" ); deleteReadingspec ($hash, ".*_PVreal" );
writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben
@ -5970,7 +5970,7 @@ sub _transferBatteryValues {
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $day = $paref->{day}; my $day = $paref->{day};
my ($badev,$a,$h) = useBattery ($name); my ($badev,$a,$h) = isBatteryUsed ($name);
return if(!$badev); return if(!$badev);
my $type = $paref->{type}; my $type = $paref->{type};
@ -6104,7 +6104,7 @@ sub _transferBatteryValues {
setPVhistory ($paref); setPVhistory ($paref);
delete $paref->{histname}; delete $paref->{histname};
###### ######
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatIn', $batinthishour.' Wh'); storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatIn', $batinthishour.' Wh');
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatOut', $batoutthishour.' Wh'); storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_BatOut', $batoutthishour.' Wh');
@ -6115,6 +6115,9 @@ sub _transferBatteryValues {
$data{$type}{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung $data{$type}{$name}{current}{powerbatin} = int $pbi; # Hilfshash Wert aktuelle Batterieladung
$data{$type}{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung $data{$type}{$name}{current}{powerbatout} = int $pbo; # Hilfshash Wert aktuelle Batterieentladung
$data{$type}{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung $data{$type}{$name}{current}{batcharge} = $soc; # aktuelle Batterieladung
push @{$data{$type}{$name}{current}{socslidereg}}, $soc; # Schieberegister Batterie SOC
limitArray ($data{$type}{$name}{current}{socslidereg}, $defslidenum);
return; return;
} }
@ -7489,7 +7492,7 @@ sub ___enableSwitchByBatPrioCharge {
my $ena = 1; my $ena = 1;
my $pcb = AttrVal ($name, 'affectBatteryPreferredCharge', 0); # Vorrangladung Batterie zu X% my $pcb = AttrVal ($name, 'affectBatteryPreferredCharge', 0); # Vorrangladung Batterie zu X%
my ($badev) = useBattery ($name); my ($badev) = isBatteryUsed ($name);
return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert
@ -7665,38 +7668,35 @@ sub _evaluateThresholds {
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $pt = ReadingsVal($name, "powerTrigger", ""); my $bt = ReadingsVal($name, 'batteryTrigger', '');
my $eh4t = ReadingsVal($name, "energyH4Trigger", ""); my $pt = ReadingsVal($name, 'powerTrigger', '');
my $eh4t = ReadingsVal($name, 'energyH4Trigger', '');
if ($bt) {
$paref->{cobj} = 'socslidereg';
$paref->{tname} = 'batteryTrigger';
$paref->{tholds} = $bt;
__evaluateArray ($paref);
}
if ($pt) { if ($pt) {
my $aaref = CurrentVal ($hash, "genslidereg", ""); $paref->{cobj} = 'genslidereg';
my @aa = (); $paref->{tname} = 'powerTrigger';
@aa = @{$aaref} if (ref $aaref eq "ARRAY"); $paref->{tholds} = $pt;
if (scalar @aa >= $defslidenum) { __evaluateArray ($paref);
$paref->{taref} = \@aa;
$paref->{tname} = "powerTrigger";
$paref->{tholds} = $pt;
__evaluateArray ($paref);
}
} }
if ($eh4t) { if ($eh4t) {
my $aaref = CurrentVal ($hash, "h4fcslidereg", ""); $paref->{cobj} = 'h4fcslidereg';
my @aa = (); $paref->{tname} = 'energyH4Trigger';
@aa = @{$aaref} if (ref $aaref eq "ARRAY"); $paref->{tholds} = $eh4t;
__evaluateArray ($paref);
}
if (scalar @aa >= $defslidenum) { delete $paref->{cobj};
$paref->{taref} = \@aa;
$paref->{tname} = "energyH4Trigger";
$paref->{tholds} = $eh4t;
__evaluateArray ($paref);
}
}
delete $paref->{taref};
delete $paref->{tname}; delete $paref->{tname};
delete $paref->{tholds}; delete $paref->{tholds};
@ -7708,14 +7708,22 @@ return;
################################################################ ################################################################
sub __evaluateArray { sub __evaluateArray {
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $taref = $paref->{taref}; # Referenz zum Threshold-Array my $cobj = $paref->{cobj}; # das CurrentVal Objekt, z.B. genslidereg
my $tname = $paref->{tname}; # Thresholdname, z.B. powerTrigger my $tname = $paref->{tname}; # Thresholdname, z.B. powerTrigger
my $tholds = $paref->{tholds}; # Triggervorgaben, z.B. aus Reading powerTrigger my $tholds = $paref->{tholds}; # Triggervorgaben, z.B. aus Reading powerTrigger
my $aaref = CurrentVal ($hash, $cobj, '');
my @aa = ();
@aa = @{$aaref} if (ref $aaref eq 'ARRAY');
return if(scalar @aa < $defslidenum);
my $gen1 = @$taref[0]; my $gen1 = @aa[0];
my $gen2 = @$taref[1]; my $gen2 = @aa[1];
my $gen3 = @$taref[2]; my $gen3 = @aa[2];
my ($a,$h) = parseParams ($tholds); my ($a,$h) = parseParams ($tholds);
@ -9112,8 +9120,8 @@ sub __createOwnSpec {
return if(!$spec || !$show); return if(!$spec || !$show);
my $allsets = getAllSets ($name); my $allsets = FW_widgetOverride($name, getAllSets ($name), "set")." ";
my $allattrs = getAllAttr ($name); my $allattrs = FW_widgetOverride($name, getAllAttr ($name), "set")." "; # Leerzeichen am Ende wichtig für Regexvergleich
my @fields = split (/\s+/sx, $spec); my @fields = split (/\s+/sx, $spec);
@ -9135,8 +9143,8 @@ sub __createOwnSpec {
for (my $i = 1 ; $i <= $rows; $i++) { for (my $i = 1 ; $i <= $rows; $i++) {
my ($h, $v, $u); my ($h, $v, $u);
for (my $k = 0 ; $k < $vinr; $k++) { for (my $k = 0 ; $k < $vinr; $k++) {
($h->{$k}{label}, $h->{$k}{rdg}) = split ":", $vals[$col] if($vals[$col]); ($h->{$k}{label}, $h->{$k}{elm}) = split ":", $vals[$col] if($vals[$col]);
$col++; $col++;
if (!$h->{$k}{label}) { if (!$h->{$k}{label}) {
@ -9144,23 +9152,31 @@ sub __createOwnSpec {
next; next;
} }
my $setcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allsets, 'set'); if ($h->{$k}{elm} !~ /@/xs) {
my $setcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allsets, 'set');
if ($setcmd) {
$v->{$k} = $setcmd; if ($setcmd) {
$u->{$k} = q{}; $v->{$k} = $setcmd;
next; $u->{$k} = q{};
next;
}
my $attrcmd = ___getFWwidget ($name, $h->{$k}{elm}, $allattrs, 'attr');
if ($attrcmd) {
$v->{$k} = $attrcmd;
$u->{$k} = q{};
next;
}
} }
my $attrcmd = ___getFWwidget ($name, $h->{$k}{rdg}, $allattrs, 'attr'); my ($rdg, $dev) = split "@", $h->{$k}{elm};
$dev //= $name;
if ($attrcmd) { ($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($dev, $rdg, '');
$v->{$k} = $attrcmd;
$u->{$k} = q{};
next;
}
($v->{$k}, $u->{$k}) = split /\s+/, ReadingsVal ($name, $h->{$k}{rdg}, ' '); $v->{$k} //= q{};
$u->{$k} //= q{};
next if(!$u->{$k}); next if(!$u->{$k});
@ -9200,7 +9216,7 @@ return $ownv;
################################################################ ################################################################
sub ___getFWwidget { sub ___getFWwidget {
my $name = shift; my $name = shift;
my $elm = shift; # Element my $elm = shift; # zu prüfendes Element
my $allc = shift; # Kommandovorrat -> ist Element enthalten? my $allc = shift; # Kommandovorrat -> ist Element enthalten?
my $ctyp = shift // 'set'; # Kommandotyp: set/attr my $ctyp = shift // 'set'; # Kommandotyp: set/attr
@ -9219,7 +9235,7 @@ sub ___getFWwidget {
if ($ctyp eq 'attr') { if ($ctyp eq 'attr') {
$current = AttrVal ($name, $elm, ''); $current = AttrVal ($name, $elm, '');
$reading = '.'.$elm; $reading = '.'.$elm;
push @attrreadings, $reading; push @attrreadings, $reading;
readingsSingleUpdate ($defs{$name}, $reading, $current, 0); readingsSingleUpdate ($defs{$name}, $reading, $current, 0);
} }
@ -9237,16 +9253,22 @@ sub ___getFWwidget {
} }
if ($ctyp eq 'attr') { if ($ctyp eq 'attr') {
my ($sc) = $widget =~ /current='(.*?)'/xs; my ($sc) = $widget =~ /current='(.*?)'/xs;
my ($sr) = $widget =~ /reading='(.*?)'/xs; my ($sr) = $widget =~ /reading='(.*?)'/xs;
$widget =~ s/$sc/$current/ if(defined $sc); $widget =~ s/$sc/$current/ if(defined $sc);
$widget =~ s/$sr/$reading/ if(defined $sr); $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 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; $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;
}
} }
#Log3 ($name, 1, qq{$name - widget: $widget});
return $widget; return $widget;
} }
@ -10596,31 +10618,16 @@ sub checkdwdattr {
return $err; return $err;
} }
################################################################
# ist Batterie installiert ?
# 1 - ja, 0 - nein
################################################################
sub useBattery {
my $name = shift;
my $badev = ReadingsVal($name, "currentBatteryDev", ""); # aktuelles Meter device für Batteriewerte
my ($a,$h) = parseParams ($badev);
$badev = $a->[0] // "";
return if(!$badev || !$defs{$badev});
return ($badev, $a ,$h);
}
################################################################ ################################################################
# Korrekturen und Qualität berechnen / speichern # Korrekturen und Qualität berechnen / speichern
# sowie AI Instanzen hinzufügen # sowie AI Quellen Daten hinzufügen
################################################################ ################################################################
sub calcValueImproves { sub calcValueImproves {
my $paref = shift; my $paref = shift;
my $hash = $paref->{hash}; my $hash = $paref->{hash};
my $name = $paref->{name}; my $name = $paref->{name};
my $chour = $paref->{chour}; my $chour = $paref->{chour};
my $t = $paref->{t}; # aktuelle Unix-Zeit my $t = $paref->{t}; # aktuelle Unix-Zeit
my $idts = ReadingsTimestamp ($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice my $idts = ReadingsTimestamp ($name, "currentInverterDev", ""); # Definitionstimestamp des Inverterdevice
return if(!$idts); return if(!$idts);
@ -10658,7 +10665,7 @@ sub calcValueImproves {
_calcCaQcomplex ($paref); # Korrekturberechnung mit Bewölkung duchführen/speichern _calcCaQcomplex ($paref); # Korrekturberechnung mit Bewölkung duchführen/speichern
_calcCaQsimple ($paref); # einfache Korrekturberechnung 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}; delete $paref->{h};
} }
@ -10829,7 +10836,7 @@ return;
} }
################################################################ ################################################################
# AI Instanz für die abgeschlossene Stunde hinzufügen # AI Daten für die abgeschlossene Stunde hinzufügen
################################################################ ################################################################
sub _addHourAiRawdata { sub _addHourAiRawdata {
my $paref = shift; my $paref = shift;
@ -10844,7 +10851,7 @@ sub _addHourAiRawdata {
debugLog ($paref, 'aiProcess', "start add AI raw data for hour: $h"); debugLog ($paref, 'aiProcess', "start add AI raw data for hour: $h");
$paref->{ood} = 1; $paref->{ood} = 1; # Only One Day
$paref->{rho} = $rho; $paref->{rho} = $rho;
aiAddRawData ($paref); # Raw Daten für AI hinzufügen und sichern aiAddRawData ($paref); # Raw Daten für AI hinzufügen und sichern
@ -13426,6 +13433,22 @@ sub isConsRcmd {
return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0); return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0);
} }
################################################################
# ist Batterie installiert ?
# 1 - ja, 0 - nein
################################################################
sub isBatteryUsed {
my $name = shift;
my $badev = ReadingsVal($name, "currentBatteryDev", ""); # aktuelles Meter device für Batteriewerte
my ($a,$h) = parseParams ($badev);
$badev = $a->[0] // "";
return if(!$badev || !$defs{$badev});
return ($badev, $a ,$h);
}
################################################################ ################################################################
# ist Consumer $c unterbrechbar (1|2) oder nicht (0|3) # ist Consumer $c unterbrechbar (1|2) oder nicht (0|3)
################################################################ ################################################################
@ -14135,6 +14158,7 @@ return $def;
# aiaddistate - Add Instanz Status der KI # aiaddistate - Add Instanz Status der KI
# genslidereg - Schieberegister PV Erzeugung (Array) # genslidereg - Schieberegister PV Erzeugung (Array)
# h4fcslidereg - Schieberegister 4h PV Forecast (Array) # h4fcslidereg - Schieberegister 4h PV Forecast (Array)
# socslidereg - Schieberegister Batterie SOC (Array)
# consumption - aktueller Verbrauch (W) # consumption - aktueller Verbrauch (W)
# consumerdevs - alle registrierten Consumerdevices (Array) # consumerdevs - alle registrierten Consumerdevices (Array)
# gridconsumption - aktueller Netzbezug # gridconsumption - aktueller Netzbezug
@ -15045,6 +15069,7 @@ to ensure that the system configuration is correct.
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="20%"> <col width="80%"> </colgroup>
<tr><td> <b>aiData</b> </td><td>deletes an existing AI instance including all training data and reinitialises it </td></tr> <tr><td> <b>aiData</b> </td><td>deletes an existing AI instance including all training data and reinitialises it </td></tr>
<tr><td> <b>batteryTriggerSet</b> </td><td>deletes the trigger points of the battery storage </td></tr>
<tr><td> <b>consumerPlanning</b> </td><td>deletes the planning data of all registered consumers </td></tr> <tr><td> <b>consumerPlanning</b> </td><td>deletes the planning data of all registered consumers </td></tr>
<tr><td> </td><td>To delete the planning data of only one consumer, use: </td></tr> <tr><td> </td><td>To delete the planning data of only one consumer, use: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Consumer number&gt; </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Consumer number&gt; </ul> </td></tr>
@ -15057,13 +15082,12 @@ to ensure that the system configuration is correct.
<tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Day&gt; (e.g. set &lt;name&gt; reset consumption 08) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Day&gt; (e.g. set &lt;name&gt; reset consumption 08) </ul> </td></tr>
<tr><td> </td><td>To delete the consumption values of a specific hour of a day: </td></tr> <tr><td> </td><td>To delete the consumption values of a specific hour of a day: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Day&gt; &lt;Hour&gt; (e.g. set &lt;name&gt; reset consumption 08 10) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Day&gt; &lt;Hour&gt; (e.g. set &lt;name&gt; reset consumption 08 10) </ul> </td></tr>
<tr><td> <b>currentBatteryDev</b> </td><td>deletes the set battery device and corresponding data. </td></tr> <tr><td> <b>currentBatterySet</b> </td><td>deletes the set battery device and corresponding data. </td></tr>
<tr><td> <b>currentWeatherDev</b> </td><td>deletes the set device for weather data </td></tr> <tr><td> <b>currentInverterSet</b> </td><td>deletes the set inverter device and corresponding data. </td></tr>
<tr><td> <b>currentInverterDev</b> </td><td>deletes the set inverter device and corresponding data. </td></tr> <tr><td> <b>currentMeterSet</b> </td><td>deletes the set meter device and corresponding data. </td></tr>
<tr><td> <b>currentMeterDev</b> </td><td>deletes the set meter device and corresponding data. </td></tr> <tr><td> <b>energyH4TriggerSet</b> </td><td>deletes the 4-hour energy trigger points </td></tr>
<tr><td> <b>energyH4Trigger</b> </td><td>deletes the 4-hour energy trigger points </td></tr> <tr><td> <b>inverterStringSet</b> </td><td>deletes the string configuration of the installation </td></tr>
<tr><td> <b>inverterStrings</b> </td><td>deletes the string configuration of the installation </td></tr> <tr><td> <b>powerTriggerSet</b> </td><td>deletes the trigger points for PV generation values </td></tr>
<tr><td> <b>powerTrigger</b> </td><td>deletes the trigger points for PV generation values </td></tr>
<tr><td> <b>pvCorrection</b> </td><td>deletes the readings pvCorrectionFactor* </td></tr> <tr><td> <b>pvCorrection</b> </td><td>deletes the readings pvCorrectionFactor* </td></tr>
<tr><td> </td><td>To delete all previously stored PV correction factors from the caches: </td></tr> <tr><td> </td><td>To delete all previously stored PV correction factors from the caches: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset pvCorrection cached </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvCorrection cached </ul> </td></tr>
@ -15075,7 +15099,7 @@ to ensure that the system configuration is correct.
<tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Day&gt; (e.g. set &lt;name&gt; reset pvHistory 08) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Day&gt; (e.g. set &lt;name&gt; reset pvHistory 08) </ul> </td></tr>
<tr><td> </td><td>To delete a specific hour of a historical day: </td></tr> <tr><td> </td><td>To delete a specific hour of a historical day: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Day&gt; &lt;Hour&gt; (e.g. set &lt;name&gt; reset pvHistory 08 10) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Day&gt; &lt;Hour&gt; (e.g. set &lt;name&gt; reset pvHistory 08 10) </ul> </td></tr>
<tr><td> <b>moduleRoofTops</b> </td><td>deletes the SolCast API Rooftops </td></tr> <tr><td> <b>moduleRoofTopSet</b> </td><td>deletes the SolCast API Rooftops </td></tr>
<tr><td> <b>roofIdentPair</b> </td><td>deletes all saved SolCast API Rooftop ID / API Key pairs. </td></tr> <tr><td> <b>roofIdentPair</b> </td><td>deletes all saved SolCast API Rooftop ID / API Key pairs. </td></tr>
<tr><td> </td><td>To delete a specific pair, specify its key &lt;pk&gt;: </td></tr> <tr><td> </td><td>To delete a specific pair, specify its key &lt;pk&gt;: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset roofIdentPair &lt;pk&gt; (e.g. set &lt;name&gt; reset roofIdentPair p1) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset roofIdentPair &lt;pk&gt; (e.g. set &lt;name&gt; reset roofIdentPair p1) </ul> </td></tr>
@ -15395,7 +15419,7 @@ to ensure that the system configuration is correct.
<a id="SolarForecast-get-valDecTree"></a> <a id="SolarForecast-get-valDecTree"></a>
<li><b>valDecTree </b> <br><br> <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> <br><br>
<ul> <ul>
@ -16407,6 +16431,27 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
</li> </li>
</ul> </ul>
<br> <br>
<ul>
<a id="SolarForecast-set-batteryTrigger"></a>
<li><b>batteryTrigger &lt;1on&gt;=&lt;Wert&gt; &lt;1off&gt;=&lt;Wert&gt; [&lt;2on&gt;=&lt;Wert&gt; &lt;2off&gt;=&lt;Wert&gt; ...] </b> <br><br>
Generiert Trigger bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SOC in %). <br>
Überschreiten die letzten drei SOC-Messungen eine definierte <b>Xon-Bedingung</b>, wird das Reading
<b>batteryTrigger_X = on</b> erstellt/gesetzt.
Unterschreiten die letzten drei SOC-Messungen eine definierte <b>Xoff-Bedingung</b>, wird das Reading
<b>batteryTrigger_X = off</b> erstellt/gesetzt. <br>
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise
definiert werden. <br>
<br>
<ul>
<b>Beispiel: </b> <br>
set &lt;name&gt; batteryTrigger 1on=30 1off=10 2on=70 2off=20 3on=15 4off=90<br>
</ul>
</li>
</ul>
<br>
<ul> <ul>
<a id="SolarForecast-set-consumerNewPlanning"></a> <a id="SolarForecast-set-consumerNewPlanning"></a>
@ -16921,6 +16966,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<table> <table>
<colgroup> <col width="20%"> <col width="80%"> </colgroup> <colgroup> <col width="20%"> <col width="80%"> </colgroup>
<tr><td> <b>aiData</b> </td><td>löscht eine vorhandene KI Instanz inklusive aller Trainingsdaten und initialisiert sie neu </td></tr> <tr><td> <b>aiData</b> </td><td>löscht eine vorhandene KI Instanz inklusive aller Trainingsdaten und initialisiert sie neu </td></tr>
<tr><td> <b>batteryTriggerSet</b> </td><td>löscht die Triggerpunkte des Batteriespeichers </td></tr>
<tr><td> <b>consumerPlanning</b> </td><td>löscht die Planungsdaten aller registrierten Verbraucher </td></tr> <tr><td> <b>consumerPlanning</b> </td><td>löscht die Planungsdaten aller registrierten Verbraucher </td></tr>
<tr><td> </td><td>Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man: </td></tr> <tr><td> </td><td>Um die Planungsdaten nur eines Verbrauchers zu löschen verwendet man: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Verbrauchernummer&gt; </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumerPlanning &lt;Verbrauchernummer&gt; </ul> </td></tr>
@ -16933,13 +16979,12 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Tag&gt; (z.B. set &lt;name&gt; reset consumption 08) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Tag&gt; (z.B. set &lt;name&gt; reset consumption 08) </ul> </td></tr>
<tr><td> </td><td>Um die Verbrauchswerte einer bestimmten Stunde eines Tages zu löschen: </td></tr> <tr><td> </td><td>Um die Verbrauchswerte einer bestimmten Stunde eines Tages zu löschen: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Tag&gt; &lt;Stunde&gt; (z.B. set &lt;name&gt; reset consumption 08 10) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset consumption &lt;Tag&gt; &lt;Stunde&gt; (z.B. set &lt;name&gt; reset consumption 08 10) </ul> </td></tr>
<tr><td> <b>currentBatteryDev</b> </td><td>löscht das eingestellte Batteriedevice und korrespondierende Daten </td></tr> <tr><td> <b>currentBatterySet</b> </td><td>löscht das eingestellte Batteriedevice und korrespondierende Daten </td></tr>
<tr><td> <b>currentWeatherDev</b> </td><td>löscht das eingestellte Device für Wetterdaten </td></tr> <tr><td> <b>currentInverterSet</b> </td><td>löscht das eingestellte Inverterdevice und korrespondierende Daten </td></tr>
<tr><td> <b>currentInverterDev</b> </td><td>löscht das eingestellte Inverterdevice und korrespondierende Daten </td></tr> <tr><td> <b>currentMeterSet</b> </td><td>löscht das eingestellte Meterdevice und korrespondierende Daten </td></tr>
<tr><td> <b>currentMeterDev</b> </td><td>löscht das eingestellte Meterdevice und korrespondierende Daten </td></tr> <tr><td> <b>energyH4TriggerSet</b> </td><td>löscht die 4-Stunden Energie Triggerpunkte </td></tr>
<tr><td> <b>energyH4Trigger</b> </td><td>löscht die 4-Stunden Energie Triggerpunkte </td></tr> <tr><td> <b>inverterStringSet</b> </td><td>löscht die Stringkonfiguration der Anlage </td></tr>
<tr><td> <b>inverterStrings</b> </td><td>löscht die Stringkonfiguration der Anlage </td></tr> <tr><td> <b>powerTriggerSet</b> </td><td>löscht die Triggerpunkte für PV Erzeugungswerte </td></tr>
<tr><td> <b>powerTrigger</b> </td><td>löscht die Triggerpunkte für PV Erzeugungswerte </td></tr>
<tr><td> <b>pvCorrection</b> </td><td>löscht die Readings pvCorrectionFactor* </td></tr> <tr><td> <b>pvCorrection</b> </td><td>löscht die Readings pvCorrectionFactor* </td></tr>
<tr><td> </td><td>Um alle bisher gespeicherten PV Korrekturfaktoren aus den Caches zu löschen: </td></tr> <tr><td> </td><td>Um alle bisher gespeicherten PV Korrekturfaktoren aus den Caches zu löschen: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset pvCorrection cached </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvCorrection cached </ul> </td></tr>
@ -16951,7 +16996,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Tag&gt; (z.B. set &lt;name&gt; reset pvHistory 08) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Tag&gt; (z.B. set &lt;name&gt; reset pvHistory 08) </ul> </td></tr>
<tr><td> </td><td>Um eine bestimmte Stunde eines historischer Tages zu löschen: </td></tr> <tr><td> </td><td>Um eine bestimmte Stunde eines historischer Tages zu löschen: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Tag&gt; &lt;Stunde&gt; (z.B. set &lt;name&gt; reset pvHistory 08 10) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset pvHistory &lt;Tag&gt; &lt;Stunde&gt; (z.B. set &lt;name&gt; reset pvHistory 08 10) </ul> </td></tr>
<tr><td> <b>moduleRoofTops</b> </td><td>löscht die SolCast API Rooftops </td></tr> <tr><td> <b>moduleRoofTopSet</b> </td><td>löscht die SolCast API Rooftops </td></tr>
<tr><td> <b>roofIdentPair</b> </td><td>löscht alle gespeicherten SolCast API Rooftop-ID / API-Key Paare </td></tr> <tr><td> <b>roofIdentPair</b> </td><td>löscht alle gespeicherten SolCast API Rooftop-ID / API-Key Paare </td></tr>
<tr><td> </td><td>Um ein bestimmtes Paar zu löschen ist dessen Schlüssel &lt;pk&gt; anzugeben: </td></tr> <tr><td> </td><td>Um ein bestimmtes Paar zu löschen ist dessen Schlüssel &lt;pk&gt; anzugeben: </td></tr>
<tr><td> </td><td><ul>set &lt;name&gt; reset roofIdentPair &lt;pk&gt; (z.B. set &lt;name&gt; reset roofIdentPair p1) </ul> </td></tr> <tr><td> </td><td><ul>set &lt;name&gt; reset roofIdentPair &lt;pk&gt; (z.B. set &lt;name&gt; reset roofIdentPair p1) </ul> </td></tr>
@ -17269,7 +17314,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<a id="SolarForecast-get-valDecTree"></a> <a id="SolarForecast-get-valDecTree"></a>
<li><b>valDecTree </b> <br><br> <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> <br><br>
<ul> <ul>
@ -17957,8 +18002,9 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<br> <br>
<a id="SolarForecast-attr-graphicHeaderOwnspec"></a> <a id="SolarForecast-attr-graphicHeaderOwnspec"></a>
<li><b>graphicHeaderOwnspec &lt;Label&gt;:&lt;Reading&gt; &lt;Label&gt;:&lt;Reading&gt; ... </b><br> <li><b>graphicHeaderOwnspec &lt;Label&gt;:&lt;Reading[@Device]&gt; &lt;Label&gt;:&lt;Reading[@Device]&gt; ... </b><br>
Anzeige beliebiger Readings, Set-Kommandos und Attribute des Devices im Grafikkopf. <br> Anzeige beliebiger Readings, Set-Kommandos und Attribute des SolarForecast Devices im Grafikkopf. <br>
Durch Angabe des optionalen [@Device] können Readings anderer Devices angezeigt werden. <br>
Die anzuzeigenden Werte werden durch Leerzeichen getrennt. Die anzuzeigenden Werte werden durch Leerzeichen getrennt.
Es werden vier Werte (Felder) pro Zeile dargestellt. <br> 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 Die Eingabe kann mehrzeilig erfolgen. Werte mit den Einheiten "Wh" bzw. "kWh" werden entsprechend der Einstellung
@ -17983,7 +18029,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
<tr><td> </td><td># </td></tr> <tr><td> </td><td># </td></tr>
<tr><td> </td><td>CO&amp;nbsp;bis&amp;nbsp;Sonnenuntergang:statistic_todayConForecastTillSunset </td></tr> <tr><td> </td><td>CO&amp;nbsp;bis&amp;nbsp;Sonnenuntergang:statistic_todayConForecastTillSunset </td></tr>
<tr><td> </td><td>PV&amp;nbsp;Übermorgen:statistic_dayAfterTomorrowPVforecast </td></tr> <tr><td> </td><td>PV&amp;nbsp;Übermorgen:statistic_dayAfterTomorrowPVforecast </td></tr>
<tr><td> </td><td>: </td></tr> <tr><td> </td><td>InverterRelay:gridrelay_status@MySTP_5000 </td></tr>
<tr><td> </td><td>: </td></tr> <tr><td> </td><td>: </td></tr>
<tr><td> </td><td>#Batterie </td></tr> <tr><td> </td><td>#Batterie </td></tr>
<tr><td> </td><td>in&amp;nbsp;heute:statistic_todayBatIn </td></tr> <tr><td> </td><td>in&amp;nbsp;heute:statistic_todayBatIn </td></tr>