mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 18:59:33 +00:00
76_SolarForecast.pm: contrib 0.53.0
git-svn-id: https://svn.fhem.de/fhem/trunk@24649 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
078e57d7e6
commit
1bd4ea3592
@ -119,6 +119,7 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"0.53.0" => "17.06.2021 Logic for preferential charging battery, attr preferredChargeBattery ",
|
||||
"0.52.5" => "16.06.2021 sub __weatherOnBeam ",
|
||||
"0.52.4" => "15.06.2021 minor fix, possible avoid implausible inverter values ",
|
||||
"0.52.3" => "14.06.2021 consumer on/off icon gray if no on/off command is defined, more consumer debug log ",
|
||||
@ -583,6 +584,7 @@ sub Initialize {
|
||||
"maxVariancePerDay ".
|
||||
"maxValBeam ".
|
||||
"numHistDays:slider,1,1,30 ".
|
||||
"preferredChargeBattery:slider,0,1,100 ".
|
||||
"rainFactorDamping:slider,0,1,100 ".
|
||||
"sameWeekdaysForConsfc:1,0 ".
|
||||
"showDiff:no,top,bottom ".
|
||||
@ -1331,7 +1333,7 @@ sub _setconsumerAction { ## no critic "not used"
|
||||
|
||||
my $action = shift @args; # z.B. set, setreading
|
||||
my $cname = shift @args; # Consumername
|
||||
my $tail = join " ", map { my $p = $_; $p =~ s/\s//xg; $p; } @args; # restliche Befehlsargumente ## no critic 'Map blocks'
|
||||
my $tail = join " ", map { my $p = $_; $p =~ s/\s//xg; $p; } @args; ## no critic 'Map blocks' # restliche Befehlsargumente
|
||||
|
||||
if($action eq "set") {
|
||||
CommandSet (undef,"$cname $tail");
|
||||
@ -1651,7 +1653,7 @@ sub Notify {
|
||||
$event = "" if(!defined($event));
|
||||
my @evl = split(/\s+/x, $event);
|
||||
|
||||
my @parts = split(/: /,$event, 2);
|
||||
my @parts = split(/: /x,$event, 2);
|
||||
my $reading = shift @parts;
|
||||
|
||||
if ($reading eq "state" || $reading eq $autoreading) {
|
||||
@ -2637,7 +2639,7 @@ sub _manageConsumerData {
|
||||
## consumer Hash ergänzen, Reading generieren
|
||||
###############################################
|
||||
my $costate = ReadingsVal ($consumer, "state", "");
|
||||
my ($pstate,$starttime,$stoptime) = __planningStateandTimes ($paref);
|
||||
my ($pstate,$starttime,$stoptime) = __planningStateAndTimes ($paref);
|
||||
$data{$type}{$name}{consumers}{$c}{state} = $costate;
|
||||
|
||||
push @$daref, "consumer${c}<>" ."name='$alias' state='$costate' planningstate='$pstate' "; # Consumer Infos
|
||||
@ -2943,14 +2945,20 @@ sub __switchConsumer {
|
||||
## Verbraucher einschalten
|
||||
############################
|
||||
my $oncom = ConsumerVal ($hash, $c, "oncom", ""); # Set Command für "on"
|
||||
my $auto = ConsumerVal ($hash, $c, "auto", 1);
|
||||
my $auto = ConsumerVal ($hash, $c, "auto", 1);
|
||||
|
||||
if($auto && $oncom && $pstate =~ /planned/xs && $startts && $t >= $startts) { # Verbraucher Start ist geplant && Startzeit überschritten
|
||||
if($auto && $oncom && $pstate =~ /planned|priority/xs && $startts && $t >= $startts) { # Verbraucher Start ist geplant && Startzeit überschritten
|
||||
my $surplus = CurrentVal ($hash, "surplus", 0); # aktueller Überschuß
|
||||
my $mode = ConsumerVal ($hash, $c, "mode", $defcmode); # Consumer Planungsmode
|
||||
my $power = ConsumerVal ($hash, $c, "power", 0); # Consumer nominale Leistungsaufnahme (W)
|
||||
my $enable = ___enableSwitchByBatPrioCharge ($paref); # Vorrangladung Batterie ?
|
||||
|
||||
if($mode eq "must" || $surplus >= $power) { # "Muss"-Planung oder Überschuß > Leistungsaufnahme
|
||||
Log3 ($name, 1, "$name - Is consumer switch enabled by battery: $enable");
|
||||
|
||||
if($mode eq "can" && !$enable) {
|
||||
$data{$type}{$name}{consumers}{$c}{planstate} = "priority charging battery";
|
||||
}
|
||||
elsif($mode eq "must" || $surplus >= $power) { # "Muss"-Planung oder Überschuß > Leistungsaufnahme
|
||||
CommandSet(undef,"$cname $oncom");
|
||||
my (undef,undef,undef,$starttime) = timestampToTimestring ($t);
|
||||
my $stopdiff = ceil(ConsumerVal ($hash, $c, "mintime", $defmintime) / 60) * 3600;
|
||||
@ -2984,10 +2992,33 @@ sub __switchConsumer {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Freigabe Einschalten Verbraucher durch Batterie Vorrangladung
|
||||
# return 0 -> keine Einschaltfreigabe Verbraucher
|
||||
# return 1 -> Einschaltfreigabe Verbraucher
|
||||
################################################################
|
||||
sub ___enableSwitchByBatPrioCharge {
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $name = $paref->{name};
|
||||
my $c = $paref->{consumer};
|
||||
|
||||
my $ena = 1;
|
||||
my $pcb = AttrVal ($name, "preferredChargeBattery", 0); # Vorrangladung Batterie zu X%
|
||||
my ($badev) = hasBattery ($name);
|
||||
|
||||
return $ena if(!$pcb || !$badev); # Freigabe Schalten Consumer wenn kein Prefered Battery/Soll-Ladung 0 oder keine Batterie installiert
|
||||
|
||||
my $cbcharge = CurrentVal ($hash, "batcharge", 0); # aktuelle Batterieladung
|
||||
$ena = 0 if($cbcharge < $pcb); # keine Freigabe wenn Batterieladung kleiner Soll-Ladung
|
||||
|
||||
return $ena;
|
||||
}
|
||||
|
||||
###################################################################
|
||||
# Consumer Planungsstatus mit Schaltzeiten liefern
|
||||
###################################################################
|
||||
sub __planningStateandTimes {
|
||||
sub __planningStateAndTimes {
|
||||
my $paref = shift;
|
||||
my $hash = $paref->{hash};
|
||||
my $c = $paref->{consumer};
|
||||
@ -2997,6 +3028,7 @@ sub __planningStateandTimes {
|
||||
$pstate = $pstate =~ /planned/xs ? "planned" :
|
||||
$pstate =~ /switched\son/xs ? "started" :
|
||||
$pstate =~ /switched\soff/xs ? "finished" :
|
||||
$pstate =~ /priority/xs ? $pstate :
|
||||
"unknown";
|
||||
|
||||
my $startts = ConsumerVal ($hash, $c, "planswitchon", "");
|
||||
@ -3021,10 +3053,8 @@ sub _transferBatteryValues {
|
||||
my $day = $paref->{day};
|
||||
my $daref = $paref->{daref};
|
||||
|
||||
my $badev = ReadingsVal($name, "currentBatteryDev", ""); # aktuelles Meter device für Batteriewerte
|
||||
my ($a,$h) = parseParams ($badev);
|
||||
$badev = $a->[0] // "";
|
||||
return if(!$badev || !$defs{$badev});
|
||||
my ($badev,$a,$h) = hasBattery ($name);
|
||||
return if(!$badev);
|
||||
|
||||
my $type = $hash->{TYPE};
|
||||
|
||||
@ -3043,16 +3073,16 @@ sub _transferBatteryValues {
|
||||
|
||||
Log3 ($name, 5, "$name - collect Battery data: device=$badev, pin=$pin ($piunit), pout=$pou ($pounit), totalin: $bin ($binunit), totalout: $bout ($boutunit), charge: $batchr");
|
||||
|
||||
my $piuf = $piunit =~ /^kW$/xi ? 1000 : 1;
|
||||
my $pouf = $pounit =~ /^kW$/xi ? 1000 : 1;
|
||||
my $binuf = $binunit =~ /^kWh$/xi ? 1000 : 1;
|
||||
my $boutuf = $boutunit =~ /^kWh$/xi ? 1000 : 1;
|
||||
my $piuf = $piunit =~ /^kW$/xi ? 1000 : 1;
|
||||
my $pouf = $pounit =~ /^kW$/xi ? 1000 : 1;
|
||||
my $binuf = $binunit =~ /^kWh$/xi ? 1000 : 1;
|
||||
my $boutuf = $boutunit =~ /^kWh$/xi ? 1000 : 1;
|
||||
|
||||
my $pbo = ReadingsNum ($badev, $pou, 0) * $pouf; # aktuelle Batterieentladung (W)
|
||||
my $pbi = ReadingsNum ($badev, $pin, 0) * $piuf; # aktueller Batterieladung (W)
|
||||
my $btotout = ReadingsNum ($badev, $bout, 0) * $boutuf; # totale Batterieentladung (Wh)
|
||||
my $btotin = ReadingsNum ($badev, $bin, 0) * $binuf; # totale Batterieladung (Wh)
|
||||
my $batcharge = ReadingsNum ($badev, $batchr, "-");
|
||||
my $pbo = ReadingsNum ($badev, $pou, 0) * $pouf; # aktuelle Batterieentladung (W)
|
||||
my $pbi = ReadingsNum ($badev, $pin, 0) * $piuf; # aktueller Batterieladung (W)
|
||||
my $btotout = ReadingsNum ($badev, $bout, 0) * $boutuf; # totale Batterieentladung (Wh)
|
||||
my $btotin = ReadingsNum ($badev, $bin, 0) * $binuf; # totale Batterieladung (Wh)
|
||||
my $batcharge = ReadingsNum ($badev, $batchr, 0);
|
||||
|
||||
my $params;
|
||||
|
||||
@ -4285,7 +4315,7 @@ sub _graphicConsumerLegend {
|
||||
|
||||
$paref->{consumer} = $c;
|
||||
|
||||
my ($planstate,$starttime,$stoptime) = __planningStateandTimes ($paref);
|
||||
my ($planstate,$starttime,$stoptime) = __planningStateAndTimes ($paref);
|
||||
my $pstate = $caicon eq "times" ? $hqtxt{pstate}{$lang} : $htitles{pstate}{$lang};
|
||||
|
||||
$pstate =~ s/<pstate>/$planstate/xs;
|
||||
@ -4300,6 +4330,11 @@ sub _graphicConsumerLegend {
|
||||
}
|
||||
else {
|
||||
$isricon = "<a title= '$htitles{conrec}{$lang}\n\n$pstate'</a>".FW_makeImage($caicon, '');
|
||||
if($planstate =~ /priority/xs) {
|
||||
my (undef,$color) = split('@', $caicon);
|
||||
$color = $color ? '@'.$color : '';
|
||||
$isricon = "<a title= '$htitles{conrec}{$lang}\n\n$pstate'</a>".FW_makeImage('it_ups_charging'.$color, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -4360,8 +4395,8 @@ sub _graphicConsumerLegend {
|
||||
$ctable .= "<td style='text-align:center' $dstyle>$auicon </td>";
|
||||
}
|
||||
else {
|
||||
my (undef,$co) = split('\@', $cicon);
|
||||
$co = '' if (!$co);
|
||||
my (undef,$co) = split('@', $cicon);
|
||||
$co = '' if (!$co);
|
||||
|
||||
$ctable .= "<td style='text-align:left' $dstyle><font color='$co'>$calias </font></td>";
|
||||
$ctable .= "<td> </td>";
|
||||
@ -4967,15 +5002,13 @@ sub _flowGraphic {
|
||||
my $grid_color = $cgfi ? 'flowg grid_color1' : 'flowg grid_color2';
|
||||
$grid_color = 'flowg grid_color3' if (!$cgfi && !$cgc && $batout); # dritte Farbe
|
||||
|
||||
my $ret;
|
||||
|
||||
$ret .= qq{
|
||||
my $ret = << "END0";
|
||||
<style>
|
||||
$css
|
||||
$animation
|
||||
</style>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5 15 380 380" style="$style" id="SVGPLOT">
|
||||
|
||||
|
||||
<g transform="translate(200,50)">
|
||||
<g>
|
||||
<line class="$sun_color" stroke-linecap="round" stroke-width="5" transform="translate(0,9)" x1="0" x2="0" y1="16" y2="24" />
|
||||
@ -5011,15 +5044,15 @@ sub _flowGraphic {
|
||||
<g id="grid" class="$grid_color" transform="translate(0,150),scale(3.5)">
|
||||
<path d="M15.3,2H8.7L2,6.46V10H4V8H8v2.79l-4,9V22H6V20.59l6-3.27,6,3.27V22h2V19.79l-4-9V8h4v2h2V6.46ZM14,4V6H10V4ZM6.3,6,8,4.87V6Zm8,6L15,13.42,12,15,9,13.42,9.65,12ZM7.11,17.71,8.2,15.25l1.71.93Zm8.68-2.46,1.09,2.46-2.8-1.53ZM14,10H10V8h4Zm2-5.13L17.7,6H16Z"/>
|
||||
</g>
|
||||
};
|
||||
END0
|
||||
|
||||
|
||||
if ($hasbat) {
|
||||
$ret .= qq{
|
||||
<g class="$bat_color" transform="translate(410,135),scale(.33) rotate (90)">
|
||||
<path d="m 134.65625,89.15625 c -6.01649,0 -11,4.983509 -11,11 l 0,180 c 0,6.01649 4.98351,11 11,11 l 95.5,0 c 6.01631,0 11,-4.9825 11,-11 l 0,-180 c 0,-6.016491 -4.98351,-11 -11,-11 l -95.5,0 z m 0,10 95.5,0 c 0.60951,0 1,0.390491 1,1 l 0,180 c 0,0.6085 -0.39231,1 -1,1 l -95.5,0 c -0.60951,0 -1,-0.39049 -1,-1 l 0,-180 c 0,-0.609509 0.39049,-1 1,-1 z"/>
|
||||
<path d="m 169.625,69.65625 c -6.01649,0 -11,4.983509 -11,11 l 0,14 10,0 0,-14 c 0,-0.609509 0.39049,-1 1,-1 l 25.5,0 c 0.60951,0 1,0.390491 1,1 l 0,14 10,0 0,-14 c 0,-6.016491 -4.98351,-11 -11,-11 l -25.5,0 z"/>
|
||||
};
|
||||
$ret .= << "END1";
|
||||
<g class="$bat_color" transform="translate(410,135),scale(.33) rotate (90)">
|
||||
<path d="m 134.65625,89.15625 c -6.01649,0 -11,4.983509 -11,11 l 0,180 c 0,6.01649 4.98351,11 11,11 l 95.5,0 c 6.01631,0 11,-4.9825 11,-11 l 0,-180 c 0,-6.016491 -4.98351,-11 -11,-11 l -95.5,0 z m 0,10 95.5,0 c 0.60951,0 1,0.390491 1,1 l 0,180 c 0,0.6085 -0.39231,1 -1,1 l -95.5,0 c -0.60951,0 -1,-0.39049 -1,-1 l 0,-180 c 0,-0.609509 0.39049,-1 1,-1 z"/>
|
||||
<path d="m 169.625,69.65625 c -6.01649,0 -11,4.983509 -11,11 l 0,14 10,0 0,-14 c 0,-0.609509 0.39049,-1 1,-1 l 25.5,0 c 0.60951,0 1,0.390491 1,1 l 0,14 10,0 0,-14 c 0,-6.016491 -4.98351,-11 -11,-11 l -25.5,0 z"/>
|
||||
END1
|
||||
|
||||
$ret .= '<path d="m 221.141,266.334 c 0,3.313 -2.688,6 -6,6 h -65.5 c -3.313,0 -6,-2.688 -6,-6 v -6 c 0,-3.314 2.687,-6 6,-6 l 65.5,-20 c 3.313,0 6,2.686 6,6 v 26 z"/>' if ($soc > 12);
|
||||
$ret .= '<path d="m 221.141,213.667 c 0,3.313 -2.688,6 -6,6 l -65.5,20 c -3.313,0 -6,-2.687 -6,-6 v -20 c 0,-3.313 2.687,-6 6,-6 l 65.5,-20 c 3.313,0 6,2.687 6,6 v 20 z"/>' if ($soc > 38);
|
||||
@ -5028,18 +5061,19 @@ sub _flowGraphic {
|
||||
$ret .= '</g>';
|
||||
}
|
||||
|
||||
$ret .= qq{
|
||||
$ret .= << "END2";
|
||||
<g transform="translate(50,50),scale(0.5)" stroke-width="27" fill="none">
|
||||
<path id="pv-home" class="$csc_style" d="M300,100 L300,510" />
|
||||
<path id="pv-grid" class="$cgfi_style" d="M270,100 L90,270" />
|
||||
<path id="grid-home" class="$cgc_style" d="M90,305 L270,510" />
|
||||
};
|
||||
<path id="pv-home" class="$csc_style" d="M300,100 L300,510" />
|
||||
<path id="pv-grid" class="$cgfi_style" d="M270,100 L90,270" />
|
||||
<path id="grid-home" class="$cgc_style" d="M90,305 L270,510" />
|
||||
END2
|
||||
|
||||
$ret .= qq{
|
||||
if ($hasbat) {
|
||||
$ret .= << "END3";
|
||||
<path id="bat-home" class="$batout_style" d="M502,305 L330,510" />
|
||||
<path id="pv-bat" class="$batin_style" d="M330,100 L500,270" />
|
||||
} if ($hasbat);
|
||||
|
||||
END3
|
||||
}
|
||||
|
||||
$ret .= qq{<text class="flowg text" id="pv-txt" x="400" y="15" style="font-size: $fs; text-anchor: start;">$cpv</text>} if ($cpv);
|
||||
$ret .= qq{<text class="flowg text" id="bat-txt" x="595" y="370" style="font-size: $fs; text-anchor: middle;">$soc %</text>} if ($hasbat);
|
||||
@ -5188,6 +5222,21 @@ sub checkdwdattr {
|
||||
return $err;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# ist Batterie installiert ?
|
||||
# 1 - ja, 0 - nein
|
||||
################################################################
|
||||
sub hasBattery {
|
||||
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);
|
||||
}
|
||||
|
||||
##################################################################################################
|
||||
# PV Forecast Rad1h in kWh / Wh
|
||||
# Berechnung nach Formel 1 aus http://www.ing-büro-junge.de/html/photovoltaik.html:
|
||||
@ -7432,6 +7481,15 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-preferredChargeBattery"></a>
|
||||
<li><b>preferredChargeBattery </b><br>
|
||||
Es werden Verbraucher mit dem Mode <b>can</b> erst dann eingeschaltet, wenn die angegebene Batterieladung (%)
|
||||
erreicht ist. <br>
|
||||
Verbraucher mit dem Mode <b>must</b> beachten die Vorrangladung der Batterie nicht. <br>
|
||||
(default: 0)
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a id="SolarForecast-attr-rainFactorDamping"></a>
|
||||
<li><b>rainFactorDamping </b><br>
|
||||
Prozentuale Berücksichtigung (Dämpfung) des Regenprognosefaktors bei der solaren Vorhersage. <br>
|
||||
|
Loading…
Reference in New Issue
Block a user