From 1a6f4d5ef01abae815594ccf8662a254c077c312 Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Tue, 10 Oct 2023 18:15:39 +0000 Subject: [PATCH] 76_SolarForecast: new consumer attr key 'noshow', minor fixes git-svn-id: https://svn.fhem.de/fhem/trunk@28043 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/76_SolarForecast.pm | 232 +++++++++++++------ fhem/contrib/DS_Starter/76_SolarForecast.pm | 238 ++++++++++++++------ 3 files changed, 323 insertions(+), 148 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 0ffb5f595..6f5deb54a 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # 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: new consumer attr key 'noshow', minor fixes - feature: 72_FRITZBOX - Log3 handling - feature: 72_FB_CALLMONITOR - Log3 handling - change: 93_DbLog: edit Commandref Forum:#135204 diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm index 94e118acb..4222b2fea 100644 --- a/fhem/FHEM/76_SolarForecast.pm +++ b/fhem/FHEM/76_SolarForecast.pm @@ -144,6 +144,8 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.0.4" => "10.10.2023 fix: print always Log in _calcCaQ* subroutines even if calaculated factors are equal ". + "new consumer attr key 'noshow' ", "1.0.3" => "08.10.2023 change graphic header PV/CO detail, new attr graphicHeaderOwnspec, internal code changes ". "fix isAddSwitchOffCond 0 Forum: https://forum.fhem.de/index.php?msg=1288877 ". "change calcValueImproves and subroutines ", @@ -969,7 +971,7 @@ sub Initialize { my $hash = shift; my $fwd = join ",", devspec2array("TYPE=FHEMWEB:FILTER=STATE=Initialized"); - my $hod = join ",", map { sprintf "%02d", $_} (01..24); + my $hod = join ",", map { sprintf "%02d", $_} (1..24); my $srd = join ",", sort keys (%hcsr); my ($consumer,@allc); @@ -1444,7 +1446,7 @@ sub _setcurrentRadiationAPI { ## no critic "not used" my $name = $paref->{name}; my $prop = $paref->{prop} // return qq{no radiation device specified}; - if($prop !~ /-API$/ && (!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData")) { + if($prop !~ /-API$/x && (!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData")) { return qq{The device "$prop" doesn't exist or has no TYPE "DWD_OpenData"}; } @@ -2073,7 +2075,7 @@ sub _setreset { ## no critic "not used" my $type = $hash->{TYPE}; - if($prop eq 'pvHistory') { + if ($prop eq 'pvHistory') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? my $dhour = $paref->{prop2} // ""; # eine bestimmte Stunde eines Tages der pvHistory angegeben ? @@ -2101,7 +2103,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'consumption') { + if ($prop eq 'consumption') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? my $dhour = $paref->{prop2} // ""; # eine bestimmte Stunde eines Tages der pvHistory angegeben ? @@ -2137,7 +2139,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'pvCorrection') { + if ($prop eq 'pvCorrection') { for my $n (1..24) { $n = sprintf "%02d", $n; deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*"); @@ -2176,7 +2178,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'aiData') { + if ($prop eq 'aiData') { delete $data{$type}{$name}{current}{aiinitstate}; delete $data{$type}{$name}{current}{aitrainstate}; delete $data{$type}{$name}{current}{aiaddistate}; @@ -2199,27 +2201,27 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'powerTrigger') { + if ($prop eq 'powerTrigger') { deleteReadingspec ($hash, "powerTrigger.*"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - if($prop eq 'energyH4Trigger') { + if ($prop eq 'energyH4Trigger') { deleteReadingspec ($hash, "energyH4Trigger.*"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - if($prop eq 'moduleRoofTops') { + if ($prop eq 'moduleRoofTops') { deleteReadingspec ($hash, "moduleRoofTops"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - readingsDelete($hash, $prop); + readingsDelete ($hash, $prop); - if($prop eq 'roofIdentPair') { + if ($prop eq 'roofIdentPair') { my $pk = $paref->{prop1} // ""; # ein bestimmter PairKey angegeben ? if ($pk) { @@ -2235,7 +2237,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'currentMeterDev') { + if ($prop eq 'currentMeterDev') { readingsDelete ($hash, "Current_GridConsumption"); readingsDelete ($hash, "Current_GridFeedIn"); delete $data{$type}{$name}{circular}{'99'}{initdayfeedin}; @@ -2253,7 +2255,7 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben } - if($prop eq 'currentBatteryDev') { + if ($prop eq 'currentBatteryDev') { readingsDelete ($hash, "Current_PowerBatIn"); readingsDelete ($hash, "Current_PowerBatOut"); readingsDelete ($hash, "Current_BatCharge"); @@ -2268,13 +2270,13 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben } - if($prop eq 'currentInverterDev') { + if ($prop eq 'currentInverterDev') { readingsDelete ($hash, "Current_PV"); deleteReadingspec ($hash, ".*_PVreal" ); 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) { @@ -2289,7 +2291,7 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben } - if($prop eq 'consumerMaster') { # Verbraucherhash löschen + if ($prop eq 'consumerMaster') { # Verbraucherhash löschen my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben if ($c) { @@ -2547,7 +2549,6 @@ sub __getSolCastData { ## statische SolCast API Kennzahlen ## (solCastAPIcallMultiplier, todayMaxAPIcalls) berechnen ########################################################## - my %seen; my %mx; my $maxcnt; @@ -5857,7 +5858,7 @@ sub _transferMeterValues { if ($docon) { my $gctotthishour = int ($gctotal - ($gcdaypast + CircularVal ($hash, 99, 'initdaygcon', 0))); - if($gctotthishour < 0) { + if ($gctotthishour < 0) { $gctotthishour = 0; } @@ -5892,7 +5893,7 @@ sub _transferMeterValues { if ($dofeed) { my $gftotthishour = int ($fitotal - ($gfdaypast + CircularVal ($hash, 99, 'initdayfeedin', 0))); - if($gftotthishour < 0) { + if ($gftotthishour < 0) { $gftotthishour = 0; } @@ -8074,6 +8075,11 @@ sub collectAllRegConsumers { if(exists $hc->{asynchron}) { $asynchron = $hc->{asynchron}; } + + my $noshow; + if(exists $hc->{noshow}) { # Consumer ausblenden in Grafik + $noshow = $hc->{noshow}; + } my ($rswstate,$onreg,$offreg); if(exists $hc->{swstate}) { @@ -8124,7 +8130,7 @@ sub collectAllRegConsumers { my $rauto = $hc->{auto} // q{}; my $ctype = $hc->{type} // $defctype; my $auto = 1; - $auto = ReadingsVal ($consumer, $rauto, 1) if($rauto); # Reading für Ready-Bit -> Einschalten möglich ? + $auto = ReadingsVal ($consumer, $rauto, 1) if($rauto); # Reading für Ready-Bit -> Einschalten möglich ? $data{$type}{$name}{consumers}{$c}{name} = $consumer; # Name des Verbrauchers (Device) $data{$type}{$name}{consumers}{$c}{alias} = $alias; # Alias des Verbrauchers (Device) @@ -8149,6 +8155,7 @@ sub collectAllRegConsumers { $data{$type}{$name}{consumers}{$c}{notafter} = $hc->{notafter} // q{}; # nicht einschalten nach Stunde in 24h Format (00-23) $data{$type}{$name}{consumers}{$c}{rswstate} = $rswstate // 'state'; # Schaltstatus Reading $data{$type}{$name}{consumers}{$c}{asynchron} = $asynchron // 0; # Arbeitsweise FHEM Consumer Device + $data{$type}{$name}{consumers}{$c}{noshow} = $noshow // 0; # ausblenden in Grafik $data{$type}{$name}{consumers}{$c}{locktime} = $clt // '0:0'; # Sperrzeit im Automatikmodus ('offlt:onlt') $data{$type}{$name}{consumers}{$c}{onreg} = $onreg // 'on'; # Regex für 'ein' $data{$type}{$name}{consumers}{$c}{offreg} = $offreg // 'off'; # Regex für 'aus' @@ -8474,7 +8481,8 @@ sub _checkSetupNotComplete { my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt my ($coset, $lat, $lon) = locCoordinates(); # Koordinaten im global device - my $rip = 1 if(exists $data{$type}{$name}{solcastapi}{'?IdPair'}); # es existiert mindestens ein Paar RoofTop-ID / API-Key + my $rip; + $rip = 1 if(exists $data{$type}{$name}{solcastapi}{'?IdPair'}); # es existiert mindestens ein Paar RoofTop-ID / API-Key my $pv0 = NexthoursVal ($hash, 'NextHour00', 'pvfc', undef); # der erste PV ForeCast Wert @@ -9153,13 +9161,13 @@ sub _graphicConsumerLegend { my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; # Consumer AdviceIcon - my ($clegendstyle, $clegend) = split('_', $paref->{clegend}); + my ($clegendstyle, $clegend) = split '_', $paref->{clegend}; my $clink = $paref->{clink}; my $type = $paref->{type}; my @consumers = sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}; # definierte Verbraucher ermitteln - $clegend = '' if(($clegendstyle eq 'none') || (!int(@consumers))); + $clegend = '' if($clegendstyle eq 'none' || !int @consumers); $paref->{clegend} = $clegend; return if(!$clegend ); @@ -9185,6 +9193,7 @@ sub _graphicConsumerLegend { $ctable .= qq{    }; my $cnum = @consumers; + if ($cnum > 1) { $ctable .= qq{ $hqtxt{cnsm}{$lang} }; $ctable .= qq{ }; @@ -9211,14 +9220,16 @@ sub _graphicConsumerLegend { my $tro = 0; for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + my $caicon = $paref->{caicon}; # Consumer AdviceIcon my ($cname, $dswname) = getCDnames ($hash, $c); # Consumer und Switch Device Name - my $calias = ConsumerVal ($hash, $c, "alias", $cname); # Alias des Consumerdevices - my $cicon = ConsumerVal ($hash, $c, "icon", ""); # Icon des Consumerdevices - my $oncom = ConsumerVal ($hash, $c, "oncom", ""); # Consumer Einschaltkommando - my $offcom = ConsumerVal ($hash, $c, "offcom", ""); # Consumer Ausschaltkommando - my $autord = ConsumerVal ($hash, $c, "autoreading", ""); # Readingname f. Automatiksteuerung - my $auto = ConsumerVal ($hash, $c, "auto", 1); # Automatic Mode + my $calias = ConsumerVal ($hash, $c, 'alias', $cname); # Alias des Consumerdevices + my $cicon = ConsumerVal ($hash, $c, 'icon', ''); # Icon des Consumerdevices + my $oncom = ConsumerVal ($hash, $c, 'oncom', ''); # Consumer Einschaltkommando + my $offcom = ConsumerVal ($hash, $c, 'offcom', ''); # Consumer Ausschaltkommando + my $autord = ConsumerVal ($hash, $c, 'autoreading', ''); # Readingname f. Automatiksteuerung + my $auto = ConsumerVal ($hash, $c, 'auto', 1); # Automatic Mode my $cmdon = qq{"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name clientAction $c 0 set $dswname $oncom')"}; my $cmdoff = qq{"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name clientAction $c 0 set $dswname $offcom')"}; @@ -9269,7 +9280,7 @@ sub _graphicConsumerLegend { else { $isricon = "".FW_makeImage($caicon, '')." "; if($planstate =~ /priority/xs) { - my (undef,$color) = split('@', $caicon); + my (undef,$color) = split '@', $caicon; $color = $color ? '@'.$color : ''; $isricon = "".FW_makeImage('batterie'.$color, '')." "; } @@ -9280,7 +9291,7 @@ sub _graphicConsumerLegend { $isricon = $pstate.'
'.$surplusinfo; } else { - ($caicon) = split('@', $caicon); + ($caicon) = split '@', $caicon; $isricon = "".FW_makeImage($caicon.'@grey', '')." "; } } @@ -9332,7 +9343,7 @@ sub _graphicConsumerLegend { $ctable .= "$auicon "; } else { - my (undef,$co) = split('@', $cicon); + my (undef,$co) = split '@', $cicon; $co = '' if (!$co); $ctable .= "$calias "; $ctable .= " "; @@ -9974,7 +9985,7 @@ sub _flowGraphic { } } - my $batout_direction = 'M902,305 L730,510'; # Batterientladung aus Netz + my $batout_direction = 'M902,305 L730,510'; # Batterientladung aus Netz if($batin) { my $gbi = $batin - $cpv; @@ -10038,8 +10049,8 @@ sub _flowGraphic { END0 - ## get consumer list and display it in Graphics - ################################################ + ## get consumer list and display in Graphics + ############################################## my $pos_left = 0; my $consumercount = 0; my $consumer_start = 0; @@ -10058,16 +10069,17 @@ END0 $consumer_start = 350 - (($consDist / 2) * ($consumercount-1)); } - #$consumer_start = 0 if $consumer_start < 0; - $pos_left = $consumer_start + 15; + $pos_left = $consumer_start + 15; - for my $c0 (@consumers) { - my $calias = ConsumerVal ($hash, $c0, "alias", ""); # Name des Consumerdevices - $currentPower = ReadingsNum ($name, "consumer${c0}_currentPower", 0); - my $cicon = __substConsumerIcon ($hash, $c0, $currentPower); # Icon des Consumerdevices - $cc_dummy -= $currentPower; + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + my $calias = ConsumerVal ($hash, $c, "alias", ""); # Name des Consumerdevices + $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); + my $cicon = __substConsumerIcon ($hash, $c, $currentPower); # Icon des Consumerdevices + $cc_dummy -= $currentPower; - $ret .= ''; + $ret .= ''; $ret .= "$calias".FW_makeImage($cicon, ''); $ret .= ' '; @@ -10137,12 +10149,14 @@ END3 $pos_left_start = 700 - ((($distance ) / 2) * ($consumercount-1)); } - for my $c1 (@consumers) { - my $power = ConsumerVal ($hash, $c1, "power", 0); - my $rpcurr = ConsumerVal ($hash, $c1, "rpcurr", ""); # Reading für akt. Verbrauch angegeben ? - $currentPower = ReadingsNum ($name, "consumer${c1}_currentPower", 0); + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + my $power = ConsumerVal ($hash, $c, "power", 0); + my $rpcurr = ConsumerVal ($hash, $c, "rpcurr", ""); # Reading für akt. Verbrauch angegeben ? + $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); - if (!$rpcurr && isConsumerPhysOn($hash, $c1)) { # Workaround wenn Verbraucher ohne Leistungsmessung + if (!$rpcurr && isConsumerPhysOn($hash, $c)) { # Workaround wenn Verbraucher ohne Leistungsmessung $currentPower = $power; } @@ -10158,8 +10172,7 @@ END3 #$chain_color = 'style="stroke: #DF0101;"'; } - $ret .= qq{}; # Design Consumer Laufkette - + $ret .= qq{}; # Design Consumer Laufkette $pos_left += ($consDist * 2); $pos_left_start += $distance; } @@ -10171,7 +10184,6 @@ END3 ## Textangaben an Grafikelementen ################################### - $ret .= qq{$cpv} if ($cpv); $ret .= qq{$soc %} if ($hasbat); # Lage Ladungs Text $ret .= qq{$csc} if ($csc && $cpv); @@ -10187,21 +10199,23 @@ END3 if ($flowgcons) { $pos_left = ($consumer_start * 2) - 50; # -XX -> Start Lage Consumer Beschriftung - for my $c2 (@consumers) { - $currentPower = sprintf "%.1f", ReadingsNum($name, "consumer${c2}_currentPower", 0); + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + $currentPower = sprintf "%.1f", ReadingsNum($name, "consumer${c}_currentPower", 0); $currentPower =~ s/\.0$// if (int($currentPower) > 0); # .0 am Ende interessiert nicht - my $consumerTime = ConsumerVal ($hash, $c2, "remainTime", ""); # Restlaufzeit - my $rpcurr = ConsumerVal ($hash, $c2, "rpcurr", ""); # Readingname f. current Power + my $consumerTime = ConsumerVal ($hash, $c, "remainTime", ""); # Restlaufzeit + my $rpcurr = ConsumerVal ($hash, $c, "rpcurr", ""); # Readingname f. current Power if (!$rpcurr) { # Workaround wenn Verbraucher ohne Leistungsmessung - $currentPower = isConsumerPhysOn($hash, $c2) ? 'on' : 'off'; + $currentPower = isConsumerPhysOn($hash, $c) ? 'on' : 'off'; } - #$ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption - #$ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit + #$ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption + #$ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit # Verbrauchszahl abhängig von der Größe entsprechend auf der x-Achse verschieben - # Hackeritis - geht mit Sicherheit auch einfacher/sinnvoller + ################################################################################## if (length($currentPower) >= 5) { $pos_left -= 40; } @@ -10218,11 +10232,11 @@ END3 $pos_left += 25; } - $ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption - $ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit + $ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption + $ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit # Verbrauchszahl abhängig von der Größe entsprechend auf der x-Achse wieder zurück an den Ursprungspunkt - # Hackeritis - geht mit Sicherheit auch einfacher/sinnvoller + ######################################################################################################### if (length($currentPower) >= 5) { $pos_left += 40; } @@ -10540,7 +10554,7 @@ sub _calcCaQcomplex { Log3 ($name, 3, "$name - new complex correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h"); } else { - Log3 ($name, 3, "$name - new complex correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac); + Log3 ($name, 3, "$name - new complex correction factor for hour $h calculated: $factor (old: $oldfac)"); } $pvre = sprintf "%.0f", $pvre; @@ -10624,7 +10638,7 @@ sub _calcCaQsimple { Log3 ($name, 3, "$name - new simple correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h"); } else { - Log3 ($name, 3, "$name - new simple correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac); + Log3 ($name, 3, "$name - new simple correction factor for hour $h calculated: $factor (old: $oldfac)"); } $pvre = sprintf "%.0f", $pvre; @@ -12913,6 +12927,30 @@ sub isConsumerLogOn { return 0; } +################################################################ +# Consumer $c in Grafik ausblenden (1) oder nicht (0) +# default: $noshow=0 +################################################################ isConsumerNoshow ($hash, $c); +sub isConsumerNoshow { + my $hash = shift; + my $c = shift; + + my $noshow = ConsumerVal ($hash, $c, 'noshow', 0); # Schalter "Ausblenden" + + if (!isNumeric ($noshow)) { # Key "noshow" enthält Signalreading + my $rdg = $noshow; + my ($dev, $dswname) = getCDnames ($hash, $c); # Consumer und Switch Device Name + + if ($noshow =~ /:/xs) { + ($dev, $rdg) = split ":", $noshow; + } + + $noshow = ReadingsNum ($dev, $rdg, 0); + } + +return $noshow; +} + ################################################################ # Funktion liefert "1" wenn die zusätzliche Einschaltbedingung # aus dem Schlüssel "swoncond" im Consumer Attribut wahr ist @@ -13317,7 +13355,8 @@ sub lastConsumerSwitchtime { my $rswstate = ConsumerVal ($hash, $c, 'rswstate', 'state'); # Reading mit Schaltstatus my $swtime = ReadingsTimestamp ($dswname, $rswstate, ''); # Zeitstempel im Format 2016-02-16 19:34:24 - my $swtimets = timestringToTimestamp ($swtime) if($swtime); # Unix Timestamp Format erzeugen + my $swtimets; + $swtimets = timestringToTimestamp ($swtime) if($swtime); # Unix Timestamp Format erzeugen return ($swtime, $swtimets); } @@ -13602,10 +13641,7 @@ sub userExit { return if(!$uefn); $uefn =~ s/\s*#.*//g; # Kommentare entfernen - - my $r; - - $uefn = join ' ', split(/\s+/sx, $uefn); # Funktion aus Attr ctrlUserExitFn serialisieren + $uefn = join ' ', split(/\s+/sx, $uefn); # Funktion aus Attr ctrlUserExitFn serialisieren if ($uefn =~ m/^\s*(\{.*\})\s*$/xs) { # unnamed Funktion direkt in ctrlUserExitFn mit {...} $uefn = $1; @@ -15196,7 +15232,7 @@ to ensure that the system configuration is correct. [notbefore=<Hour>] [notafter=<Hour>] [locktime=<offlt>[:<onlt>]]
[auto=<Readingname>] [pcurr=<Readingname>:<Unit>[:<Threshold>]] [etotal=<Readingname>:<Einheit>[:<Threshold>]]
[swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>] [spignorecond=<Device>:<Reading>:<Regex>]
- [interruptable=<Option>]
+ [interruptable=<Option>] [noshow=<Option>]

Registers a consumer <Device Name> with the SolarForecast Device. In this case, <Device Name> @@ -15245,17 +15281,22 @@ to ensure that the system configuration is correct. noSchedule - there is no scheduling or automatic switching for the consumer.                        Display functions or manual switching are available. + power nominal power consumption of the consumer (see data sheet) in W (can be set to "0") + switchdev The specified <device> is assigned to the consumer as a switch device (optional). Switching operations are performed with this device. The key is useful for consumers where energy measurement and switching is carried out with different devices e.g. Homematic or readingsProxy. If switchdev is specified, the keys on, off, swstate and asynchronous refer to this device. + mode Consumer planning mode (optional). Allowed are: can - Scheduling takes place at the time when there is probably enough PV surplus available (default).          The consumer is not started at the time of planning if the PV surplus is insufficient. must - The consumer is optimally planned, even if there will probably not be enough PV surplus.            The consumer is started even if there is insufficient PV surplus. + icon Icon to represent the consumer in the overview graphic (optional) + mintime Scheduling duration (minutes or "SunPath") of the consumer. (optional) By specifying SunPath, planning is done according to sunrise and sunset. @@ -15273,36 +15314,48 @@ to ensure that the system configuration is correct. - other: 60 minutes on Set command for switching on the consumer (optional) + off Set command for switching off the consumer (optional) + swstate Reading which indicates the switching status of the consumer (default: 'state'). on-Regex - regular expression for the state 'on' (default: 'on') off-Regex - regular expression for the state 'off' (default: 'off') + asynchron the type of switching status determination in the consumer device. The status of the consumer is only determined after a switching command . by polling within a data collection interval (synchronous) or additionally by event processing (asynchronous). 0 - only synchronous processing of switching states (default) 1 - additional asynchronous processing of switching states through event processing + notbefore Schedule start time consumer not before specified hour (01..23) (optional) + notafter Schedule start time consumer not after specified hour (01..23) (optional) + auto Reading in the consumer device which enables or blocks the switching of the consumer (optional) Reading value = 1 - switching enabled (default), 0: switching blocked + pcurr Reading:Unit (W/kW) which provides the current energy consumption (optional) :<Threshold> (W) - From this power reference on, the consumer is considered active. The specification is optional (default: 0) + etotal Reading:Unit (Wh/kWh) of the consumer device that supplies the sum of the consumed energy (optional) :<Threshold> (Wh) - From this energy consumption per hour, the consumption is considered valid. Optional specification (default: 0) + swoncond Condition that must also be fulfilled in order to switch on the consumer (optional). The scheduled cycle is started. Device - Device to supply the additional switch-on condition Reading - Reading for delivery of the additional switch-on condition Regex - regular expression that must be satisfied for a 'true' condition to be true + swoffcond priority condition to switch off the consumer (optional). The scheduled cycle is stopped. Device - Device to supply the priority switch-off condition Reading - Reading for the delivery of the priority switch-off condition Regex - regular expression that must be satisfied for a 'true' condition to be true + spignorecond Condition to ignore a missing PV surplus (optional). If the condition is fulfilled, the load is switched on according to the planning even if there is no PV surplus at the time. CAUTION: Using both keys spignorecond and interruptable can lead to undesired behaviour! Device - Device to deliver the condition Reading - Reading which contains the condition Regex - regular expression that must be satisfied for a 'true' condition to be true + interruptable defines the possible interruption options for the consumer after it has been started (optional) 0 - Load is not temporarily switched off even if the PV surplus falls below the required energy (default) 1 - Load is temporarily switched off if the PV surplus falls below the required energy @@ -15312,11 +15365,19 @@ to ensure that the system configuration is correct. PV surplus provided (if power is not 0). The optional hysteresis is a numerical value by which the switch-off point is raised if the evaluated reading value is also numeric. (default: 0) + locktime Blocking times in seconds for switching the consumer (optional). offlt - Blocking time in seconds after the consumer has been switched off or interrupted onlt - Blocking time in seconds after the consumer has been switched on or continued The consumer is only switched again when the corresponding blocking time has elapsed. Note: The 'locktime' switch is only effective in automatic mode. + + noshow Hide or show consumers in graphic (optional). + 0 - the consumer is displayed (default) + 1 - the consumer is hidden + [Device:]Reading - Reading in the consumer or optionally an alternative device. + If the reading has the value "0" or is not present, the consumer is displayed. + If the reading has the value "1", the consumer is hidden.
@@ -15329,7 +15390,7 @@ to ensure that the system configuration is correct. attr <name> consumer04 Shelly.shellyplug3 icon=scene_microwave_oven type=heater power=2000 mode=must notbefore=07 mintime=600 on=on off=off etotal=relay_0_energy_Wh:Wh pcurr=relay_0_power:W auto=automatic interruptable=eg.wz.wandthermostat:diff-temp:(22)(\.[2-9])|([2-9][3-9])(\.[0-9]):0.2
attr <name> consumer05 Shelly.shellyplug4 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath interruptable=1
attr <name> consumer06 Shelly.shellyplug5 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath:60:-120 interruptable=1
- attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1
+ attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1 noshow=noShow

@@ -16982,7 +17043,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. [notbefore=<Stunde>] [notafter=<Stunde>] [locktime=<offlt>[:<onlt>]]
[auto=<Readingname>] [pcurr=<Readingname>:<Einheit>[:<Schwellenwert>]] [etotal=<Readingname>:<Einheit>[:<Schwellenwert>]]
[swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>] [spignorecond=<Device>:<Reading>:<Regex>]
- [interruptable=<Option>]
+ [interruptable=<Option>] [noshow=<Option>]

Registriert einen Verbraucher <Device Name> beim SolarForecast Device. Dabei ist <Device Name> @@ -17030,17 +17091,22 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. noSchedule - für den Verbraucher erfolgt keine Einplanung oder automatische Schaltung.                        Anzeigefunktionen oder manuelle Schaltungen sind verfügbar. + power nominale Leistungsaufnahme des Verbrauchers (siehe Datenblatt) in W (kann auf "0" gesetzt werden) + switchdev Das angegebene <device> wird als Schalter Device dem Verbraucher zugeordnet (optional). Schaltvorgänge werden mit diesem Gerät ausgeführt. Der Schlüssel ist für Verbraucher nützlich bei denen Energiemessung und Schaltung mit verschiedenen Geräten vorgenommen wird, z.B. Homematic oder readingsProxy. Ist switchdev angegeben, beziehen sich die Schlüssel on, off, swstate und asynchron auf dieses Gerät. + mode Planungsmodus des Verbrauchers (optional). Erlaubt sind: can - Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuß (default)          Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuß. must - der Verbraucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuß vorhanden sein wird            Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuß. + icon Icon zur Darstellung des Verbrauchers in der Übersichtsgrafik (optional) + mintime Einplanungsdauer (Minuten oder "SunPath") des Verbrauchers. (optional) Mit der Angabe von SunPath erfolgt die Planung entsprechend des Sonnenauf- und untergangs. @@ -17058,36 +17124,48 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. - other: 60 Minuten on Set-Kommando zum Einschalten des Verbrauchers (optional) + off Set-Kommando zum Ausschalten des Verbrauchers (optional) + swstate Reading welches den Schaltzustand des Verbrauchers anzeigt (default: 'state'). on-Regex - regulärer Ausdruck für den Zustand 'ein' (default: 'on') off-Regex - regulärer Ausdruck für den Zustand 'aus' (default: 'off') + asynchron die Art der Schaltstatus Ermittlung im Verbraucher Device. Die Statusermittlung des Verbrauchers nach einem Schaltbefehl erfolgt nur durch Abfrage innerhalb eines Datensammelintervals (synchron) oder zusätzlich durch Eventverarbeitung (asynchron). 0 - ausschließlich synchrone Verarbeitung von Schaltzuständen (default) 1 - zusätzlich asynchrone Verarbeitung von Schaltzuständen durch Eventverarbeitung + notbefore Startzeitpunkt Verbraucher nicht vor angegebener Stunde (01..23) einplanen (optional) + notafter Startzeitpunkt Verbraucher nicht nach angegebener Stunde (01..23) einplanen (optional) + auto Reading im Verbraucherdevice welches das Schalten des Verbrauchers freigibt bzw. blockiert (optional) Readingwert = 1 - Schalten freigegeben (default), 0: Schalten blockiert + pcurr Reading:Einheit (W/kW) welches den aktuellen Energieverbrauch liefert (optional) :<Schwellenwert> (W) - Ab diesem Leistungsbezug wird der Verbraucher als aktiv gewertet. Die Angabe ist optional (default: 0) + etotal Reading:Einheit (Wh/kWh) des Consumer Device, welches die Summe der verbrauchten Energie liefert (optional) :<Schwellenwert> (Wh) - Ab diesem Energieverbrauch pro Stunde wird der Verbrauch als gültig gewertet. Optionale Angabe (default: 0) + swoncond Bedingung die zusätzlich erfüllt sein muß um den Verbraucher einzuschalten (optional). Der geplante Zyklus wird gestartet. Device - Device zur Lieferung der zusätzlichen Einschaltbedingung Reading - Reading zur Lieferung der zusätzlichen Einschaltbedingung Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + swoffcond vorrangige Bedingung um den Verbraucher auszuschalten (optional). Der geplante Zyklus wird gestoppt. Device - Device zur Lieferung der vorrangigen Ausschaltbedingung Reading - Reading zur Lieferung der vorrangigen Ausschaltbedingung Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + spignorecond Bedingung um einen fehlenden PV Überschuß zu ignorieren (optional). Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuß vorliegt. ACHTUNG: Die Verwendung beider Schlüssel spignorecond und interruptable kann zu einem unerwünschten Verhalten führen! Device - Device zur Lieferung der Bedingung Reading - Reading welches die Bedingung enthält Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + interruptable definiert die möglichen Unterbrechungsoptionen für den Verbraucher nachdem er gestartet wurde (optional) 0 - Verbraucher wird nicht temporär ausgeschaltet auch wenn der PV Überschuß die benötigte Energie unterschreitet (default) 1 - Verbraucher wird temporär ausgeschaltet falls der PV Überschuß die benötigte Energie unterschreitet @@ -17097,11 +17175,19 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. PV Überschuß (wenn power ungleich 0) vorliegt. Die optionale Hysterese ist ein numerischer Wert um den der Ausschaltpunkt gegenüber dem Soll-Einschaltpunkt angehoben wird sofern der ausgewertete Readingwert ebenfalls numerisch ist. (default: 0) + locktime Sperrzeiten in Sekunden für die Schaltung des Verbrauchers (optional). offlt - Sperrzeit in Sekunden nachdem der Verbraucher ausgeschaltet oder unterbrochen wurde onlt - Sperrzeit in Sekunden nachdem der Verbraucher eingeschaltet oder fortgesetzt wurde Der Verbraucher wird erst wieder geschaltet wenn die entsprechende Sperrzeit abgelaufen ist. Hinweis: Der Schalter 'locktime' ist nur im Automatik-Modus wirksam. + + noshow Verbraucher in Grafik ausblenden oder einblenden (optional). + 0 - der Verbraucher wird eingeblendet (default) + 1 - der Verbraucher wird ausgeblendet + [Device:]Reading - Reading im Verbraucher oder optional einem alternativen Device. + Hat das Reading den Wert "0" oder ist nicht vorhanden, wird der Verbraucher eingeblendet. + Hat das Reading den Wert "1", wird der Verbraucher ausgeblendet.
@@ -17114,7 +17200,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. attr <name> consumer04 Shelly.shellyplug3 icon=scene_microwave_oven type=heater power=2000 mode=must notbefore=07 mintime=600 on=on off=off etotal=relay_0_energy_Wh:Wh pcurr=relay_0_power:W auto=automatic interruptable=eg.wz.wandthermostat:diff-temp:(22)(\.[2-9])|([2-9][3-9])(\.[0-9]):0.2
attr <name> consumer05 Shelly.shellyplug4 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath interruptable=1
attr <name> consumer06 Shelly.shellyplug5 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath:60:-120 interruptable=1
- attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1
+ attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1 noshow=noShow

diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 95987e414..4222b2fea 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -144,6 +144,8 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "1.0.4" => "10.10.2023 fix: print always Log in _calcCaQ* subroutines even if calaculated factors are equal ". + "new consumer attr key 'noshow' ", "1.0.3" => "08.10.2023 change graphic header PV/CO detail, new attr graphicHeaderOwnspec, internal code changes ". "fix isAddSwitchOffCond 0 Forum: https://forum.fhem.de/index.php?msg=1288877 ". "change calcValueImproves and subroutines ", @@ -969,7 +971,7 @@ sub Initialize { my $hash = shift; my $fwd = join ",", devspec2array("TYPE=FHEMWEB:FILTER=STATE=Initialized"); - my $hod = join ",", map { sprintf "%02d", $_} (01..24); + my $hod = join ",", map { sprintf "%02d", $_} (1..24); my $srd = join ",", sort keys (%hcsr); my ($consumer,@allc); @@ -1444,7 +1446,7 @@ sub _setcurrentRadiationAPI { ## no critic "not used" my $name = $paref->{name}; my $prop = $paref->{prop} // return qq{no radiation device specified}; - if($prop !~ /-API$/ && (!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData")) { + if($prop !~ /-API$/x && (!$defs{$prop} || $defs{$prop}{TYPE} ne "DWD_OpenData")) { return qq{The device "$prop" doesn't exist or has no TYPE "DWD_OpenData"}; } @@ -2073,7 +2075,7 @@ sub _setreset { ## no critic "not used" my $type = $hash->{TYPE}; - if($prop eq 'pvHistory') { + if ($prop eq 'pvHistory') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? my $dhour = $paref->{prop2} // ""; # eine bestimmte Stunde eines Tages der pvHistory angegeben ? @@ -2101,7 +2103,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'consumption') { + if ($prop eq 'consumption') { my $dday = $paref->{prop1} // ""; # ein bestimmter Tag der pvHistory angegeben ? my $dhour = $paref->{prop2} // ""; # eine bestimmte Stunde eines Tages der pvHistory angegeben ? @@ -2137,7 +2139,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'pvCorrection') { + if ($prop eq 'pvCorrection') { for my $n (1..24) { $n = sprintf "%02d", $n; deleteReadingspec ($hash, "pvCorrectionFactor_${n}.*"); @@ -2176,7 +2178,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'aiData') { + if ($prop eq 'aiData') { delete $data{$type}{$name}{current}{aiinitstate}; delete $data{$type}{$name}{current}{aitrainstate}; delete $data{$type}{$name}{current}{aiaddistate}; @@ -2199,27 +2201,27 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'powerTrigger') { + if ($prop eq 'powerTrigger') { deleteReadingspec ($hash, "powerTrigger.*"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - if($prop eq 'energyH4Trigger') { + if ($prop eq 'energyH4Trigger') { deleteReadingspec ($hash, "energyH4Trigger.*"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - if($prop eq 'moduleRoofTops') { + if ($prop eq 'moduleRoofTops') { deleteReadingspec ($hash, "moduleRoofTops"); writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben return; } - readingsDelete($hash, $prop); + readingsDelete ($hash, $prop); - if($prop eq 'roofIdentPair') { + if ($prop eq 'roofIdentPair') { my $pk = $paref->{prop1} // ""; # ein bestimmter PairKey angegeben ? if ($pk) { @@ -2235,7 +2237,7 @@ sub _setreset { ## no critic "not used" return; } - if($prop eq 'currentMeterDev') { + if ($prop eq 'currentMeterDev') { readingsDelete ($hash, "Current_GridConsumption"); readingsDelete ($hash, "Current_GridFeedIn"); delete $data{$type}{$name}{circular}{'99'}{initdayfeedin}; @@ -2253,7 +2255,7 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben } - if($prop eq 'currentBatteryDev') { + if ($prop eq 'currentBatteryDev') { readingsDelete ($hash, "Current_PowerBatIn"); readingsDelete ($hash, "Current_PowerBatOut"); readingsDelete ($hash, "Current_BatCharge"); @@ -2268,13 +2270,13 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "plantconfig", $plantcfg.$name); # Anlagenkonfiguration File schreiben } - if($prop eq 'currentInverterDev') { + if ($prop eq 'currentInverterDev') { readingsDelete ($hash, "Current_PV"); deleteReadingspec ($hash, ".*_PVreal" ); 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) { @@ -2289,7 +2291,7 @@ sub _setreset { ## no critic "not used" writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben } - if($prop eq 'consumerMaster') { # Verbraucherhash löschen + if ($prop eq 'consumerMaster') { # Verbraucherhash löschen my $c = $paref->{prop1} // ""; # bestimmten Verbraucher setzen falls angegeben if ($c) { @@ -2547,7 +2549,6 @@ sub __getSolCastData { ## statische SolCast API Kennzahlen ## (solCastAPIcallMultiplier, todayMaxAPIcalls) berechnen ########################################################## - my %seen; my %mx; my $maxcnt; @@ -5857,7 +5858,7 @@ sub _transferMeterValues { if ($docon) { my $gctotthishour = int ($gctotal - ($gcdaypast + CircularVal ($hash, 99, 'initdaygcon', 0))); - if($gctotthishour < 0) { + if ($gctotthishour < 0) { $gctotthishour = 0; } @@ -5892,7 +5893,7 @@ sub _transferMeterValues { if ($dofeed) { my $gftotthishour = int ($fitotal - ($gfdaypast + CircularVal ($hash, 99, 'initdayfeedin', 0))); - if($gftotthishour < 0) { + if ($gftotthishour < 0) { $gftotthishour = 0; } @@ -8074,6 +8075,11 @@ sub collectAllRegConsumers { if(exists $hc->{asynchron}) { $asynchron = $hc->{asynchron}; } + + my $noshow; + if(exists $hc->{noshow}) { # Consumer ausblenden in Grafik + $noshow = $hc->{noshow}; + } my ($rswstate,$onreg,$offreg); if(exists $hc->{swstate}) { @@ -8124,7 +8130,7 @@ sub collectAllRegConsumers { my $rauto = $hc->{auto} // q{}; my $ctype = $hc->{type} // $defctype; my $auto = 1; - $auto = ReadingsVal ($consumer, $rauto, 1) if($rauto); # Reading für Ready-Bit -> Einschalten möglich ? + $auto = ReadingsVal ($consumer, $rauto, 1) if($rauto); # Reading für Ready-Bit -> Einschalten möglich ? $data{$type}{$name}{consumers}{$c}{name} = $consumer; # Name des Verbrauchers (Device) $data{$type}{$name}{consumers}{$c}{alias} = $alias; # Alias des Verbrauchers (Device) @@ -8149,6 +8155,7 @@ sub collectAllRegConsumers { $data{$type}{$name}{consumers}{$c}{notafter} = $hc->{notafter} // q{}; # nicht einschalten nach Stunde in 24h Format (00-23) $data{$type}{$name}{consumers}{$c}{rswstate} = $rswstate // 'state'; # Schaltstatus Reading $data{$type}{$name}{consumers}{$c}{asynchron} = $asynchron // 0; # Arbeitsweise FHEM Consumer Device + $data{$type}{$name}{consumers}{$c}{noshow} = $noshow // 0; # ausblenden in Grafik $data{$type}{$name}{consumers}{$c}{locktime} = $clt // '0:0'; # Sperrzeit im Automatikmodus ('offlt:onlt') $data{$type}{$name}{consumers}{$c}{onreg} = $onreg // 'on'; # Regex für 'ein' $data{$type}{$name}{consumers}{$c}{offreg} = $offreg // 'off'; # Regex für 'aus' @@ -8474,7 +8481,8 @@ sub _checkSetupNotComplete { my $vrmcr = SolCastAPIVal ($hash, '?VRM', '?API', 'credentials', ''); # Victron VRM Credentials gesetzt my ($coset, $lat, $lon) = locCoordinates(); # Koordinaten im global device - my $rip = 1 if(exists $data{$type}{$name}{solcastapi}{'?IdPair'}); # es existiert mindestens ein Paar RoofTop-ID / API-Key + my $rip; + $rip = 1 if(exists $data{$type}{$name}{solcastapi}{'?IdPair'}); # es existiert mindestens ein Paar RoofTop-ID / API-Key my $pv0 = NexthoursVal ($hash, 'NextHour00', 'pvfc', undef); # der erste PV ForeCast Wert @@ -9153,13 +9161,13 @@ sub _graphicConsumerLegend { my $paref = shift; my $hash = $paref->{hash}; my $name = $paref->{name}; # Consumer AdviceIcon - my ($clegendstyle, $clegend) = split('_', $paref->{clegend}); + my ($clegendstyle, $clegend) = split '_', $paref->{clegend}; my $clink = $paref->{clink}; my $type = $paref->{type}; my @consumers = sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}; # definierte Verbraucher ermitteln - $clegend = '' if(($clegendstyle eq 'none') || (!int(@consumers))); + $clegend = '' if($clegendstyle eq 'none' || !int @consumers); $paref->{clegend} = $clegend; return if(!$clegend ); @@ -9185,6 +9193,7 @@ sub _graphicConsumerLegend { $ctable .= qq{    }; my $cnum = @consumers; + if ($cnum > 1) { $ctable .= qq{ $hqtxt{cnsm}{$lang} }; $ctable .= qq{ }; @@ -9211,14 +9220,16 @@ sub _graphicConsumerLegend { my $tro = 0; for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + my $caicon = $paref->{caicon}; # Consumer AdviceIcon my ($cname, $dswname) = getCDnames ($hash, $c); # Consumer und Switch Device Name - my $calias = ConsumerVal ($hash, $c, "alias", $cname); # Alias des Consumerdevices - my $cicon = ConsumerVal ($hash, $c, "icon", ""); # Icon des Consumerdevices - my $oncom = ConsumerVal ($hash, $c, "oncom", ""); # Consumer Einschaltkommando - my $offcom = ConsumerVal ($hash, $c, "offcom", ""); # Consumer Ausschaltkommando - my $autord = ConsumerVal ($hash, $c, "autoreading", ""); # Readingname f. Automatiksteuerung - my $auto = ConsumerVal ($hash, $c, "auto", 1); # Automatic Mode + my $calias = ConsumerVal ($hash, $c, 'alias', $cname); # Alias des Consumerdevices + my $cicon = ConsumerVal ($hash, $c, 'icon', ''); # Icon des Consumerdevices + my $oncom = ConsumerVal ($hash, $c, 'oncom', ''); # Consumer Einschaltkommando + my $offcom = ConsumerVal ($hash, $c, 'offcom', ''); # Consumer Ausschaltkommando + my $autord = ConsumerVal ($hash, $c, 'autoreading', ''); # Readingname f. Automatiksteuerung + my $auto = ConsumerVal ($hash, $c, 'auto', 1); # Automatic Mode my $cmdon = qq{"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name clientAction $c 0 set $dswname $oncom')"}; my $cmdoff = qq{"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name clientAction $c 0 set $dswname $offcom')"}; @@ -9269,7 +9280,7 @@ sub _graphicConsumerLegend { else { $isricon = "".FW_makeImage($caicon, '')." "; if($planstate =~ /priority/xs) { - my (undef,$color) = split('@', $caicon); + my (undef,$color) = split '@', $caicon; $color = $color ? '@'.$color : ''; $isricon = "".FW_makeImage('batterie'.$color, '')." "; } @@ -9280,7 +9291,7 @@ sub _graphicConsumerLegend { $isricon = $pstate.'
'.$surplusinfo; } else { - ($caicon) = split('@', $caicon); + ($caicon) = split '@', $caicon; $isricon = "".FW_makeImage($caicon.'@grey', '')." "; } } @@ -9332,7 +9343,7 @@ sub _graphicConsumerLegend { $ctable .= "$auicon "; } else { - my (undef,$co) = split('@', $cicon); + my (undef,$co) = split '@', $cicon; $co = '' if (!$co); $ctable .= "$calias "; $ctable .= " "; @@ -9974,7 +9985,7 @@ sub _flowGraphic { } } - my $batout_direction = 'M902,305 L730,510'; # Batterientladung aus Netz + my $batout_direction = 'M902,305 L730,510'; # Batterientladung aus Netz if($batin) { my $gbi = $batin - $cpv; @@ -10038,8 +10049,8 @@ sub _flowGraphic {
END0 - ## get consumer list and display it in Graphics - ################################################ + ## get consumer list and display in Graphics + ############################################## my $pos_left = 0; my $consumercount = 0; my $consumer_start = 0; @@ -10058,16 +10069,17 @@ END0 $consumer_start = 350 - (($consDist / 2) * ($consumercount-1)); } - #$consumer_start = 0 if $consumer_start < 0; - $pos_left = $consumer_start + 15; + $pos_left = $consumer_start + 15; - for my $c0 (@consumers) { - my $calias = ConsumerVal ($hash, $c0, "alias", ""); # Name des Consumerdevices - $currentPower = ReadingsNum ($name, "consumer${c0}_currentPower", 0); - my $cicon = __substConsumerIcon ($hash, $c0, $currentPower); # Icon des Consumerdevices - $cc_dummy -= $currentPower; + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + my $calias = ConsumerVal ($hash, $c, "alias", ""); # Name des Consumerdevices + $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); + my $cicon = __substConsumerIcon ($hash, $c, $currentPower); # Icon des Consumerdevices + $cc_dummy -= $currentPower; - $ret .= ''; + $ret .= ''; $ret .= "$calias".FW_makeImage($cicon, ''); $ret .= ' '; @@ -10137,12 +10149,14 @@ END3 $pos_left_start = 700 - ((($distance ) / 2) * ($consumercount-1)); } - for my $c1 (@consumers) { - my $power = ConsumerVal ($hash, $c1, "power", 0); - my $rpcurr = ConsumerVal ($hash, $c1, "rpcurr", ""); # Reading für akt. Verbrauch angegeben ? - $currentPower = ReadingsNum ($name, "consumer${c1}_currentPower", 0); + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + my $power = ConsumerVal ($hash, $c, "power", 0); + my $rpcurr = ConsumerVal ($hash, $c, "rpcurr", ""); # Reading für akt. Verbrauch angegeben ? + $currentPower = ReadingsNum ($name, "consumer${c}_currentPower", 0); - if (!$rpcurr && isConsumerPhysOn($hash, $c1)) { # Workaround wenn Verbraucher ohne Leistungsmessung + if (!$rpcurr && isConsumerPhysOn($hash, $c)) { # Workaround wenn Verbraucher ohne Leistungsmessung $currentPower = $power; } @@ -10158,8 +10172,7 @@ END3 #$chain_color = 'style="stroke: #DF0101;"'; } - $ret .= qq{}; # Design Consumer Laufkette - + $ret .= qq{}; # Design Consumer Laufkette $pos_left += ($consDist * 2); $pos_left_start += $distance; } @@ -10171,7 +10184,6 @@ END3 ## Textangaben an Grafikelementen ################################### - $ret .= qq{$cpv} if ($cpv); $ret .= qq{$soc %} if ($hasbat); # Lage Ladungs Text $ret .= qq{$csc} if ($csc && $cpv); @@ -10187,21 +10199,23 @@ END3 if ($flowgcons) { $pos_left = ($consumer_start * 2) - 50; # -XX -> Start Lage Consumer Beschriftung - for my $c2 (@consumers) { - $currentPower = sprintf "%.1f", ReadingsNum($name, "consumer${c2}_currentPower", 0); + for my $c (@consumers) { + next if(isConsumerNoshow ($hash, $c)); # Consumer ausblenden + + $currentPower = sprintf "%.1f", ReadingsNum($name, "consumer${c}_currentPower", 0); $currentPower =~ s/\.0$// if (int($currentPower) > 0); # .0 am Ende interessiert nicht - my $consumerTime = ConsumerVal ($hash, $c2, "remainTime", ""); # Restlaufzeit - my $rpcurr = ConsumerVal ($hash, $c2, "rpcurr", ""); # Readingname f. current Power + my $consumerTime = ConsumerVal ($hash, $c, "remainTime", ""); # Restlaufzeit + my $rpcurr = ConsumerVal ($hash, $c, "rpcurr", ""); # Readingname f. current Power if (!$rpcurr) { # Workaround wenn Verbraucher ohne Leistungsmessung - $currentPower = isConsumerPhysOn($hash, $c2) ? 'on' : 'off'; + $currentPower = isConsumerPhysOn($hash, $c) ? 'on' : 'off'; } - #$ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption - #$ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit + #$ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption + #$ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit # Verbrauchszahl abhängig von der Größe entsprechend auf der x-Achse verschieben - # Hackeritis - geht mit Sicherheit auch einfacher/sinnvoller + ################################################################################## if (length($currentPower) >= 5) { $pos_left -= 40; } @@ -10218,11 +10232,11 @@ END3 $pos_left += 25; } - $ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption - $ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit + $ret .= qq{$currentPower} if ($flowgconPower); # Lage Consumer Consumption + $ret .= qq{$consumerTime} if ($flowgconTime); # Lage Consumer Restlaufzeit # Verbrauchszahl abhängig von der Größe entsprechend auf der x-Achse wieder zurück an den Ursprungspunkt - # Hackeritis - geht mit Sicherheit auch einfacher/sinnvoller + ######################################################################################################### if (length($currentPower) >= 5) { $pos_left += 40; } @@ -10540,7 +10554,7 @@ sub _calcCaQcomplex { Log3 ($name, 3, "$name - new complex correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h"); } else { - Log3 ($name, 3, "$name - new complex correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac); + Log3 ($name, 3, "$name - new complex correction factor for hour $h calculated: $factor (old: $oldfac)"); } $pvre = sprintf "%.0f", $pvre; @@ -10624,7 +10638,7 @@ sub _calcCaQsimple { Log3 ($name, 3, "$name - new simple correction factor calculated (limited by affectMaxDayVariance): $factor (old: $oldfac) for hour: $h"); } else { - Log3 ($name, 3, "$name - new simple correction factor for hour $h calculated: $factor (old: $oldfac)") if($factor != $oldfac); + Log3 ($name, 3, "$name - new simple correction factor for hour $h calculated: $factor (old: $oldfac)"); } $pvre = sprintf "%.0f", $pvre; @@ -12913,6 +12927,30 @@ sub isConsumerLogOn { return 0; } +################################################################ +# Consumer $c in Grafik ausblenden (1) oder nicht (0) +# default: $noshow=0 +################################################################ isConsumerNoshow ($hash, $c); +sub isConsumerNoshow { + my $hash = shift; + my $c = shift; + + my $noshow = ConsumerVal ($hash, $c, 'noshow', 0); # Schalter "Ausblenden" + + if (!isNumeric ($noshow)) { # Key "noshow" enthält Signalreading + my $rdg = $noshow; + my ($dev, $dswname) = getCDnames ($hash, $c); # Consumer und Switch Device Name + + if ($noshow =~ /:/xs) { + ($dev, $rdg) = split ":", $noshow; + } + + $noshow = ReadingsNum ($dev, $rdg, 0); + } + +return $noshow; +} + ################################################################ # Funktion liefert "1" wenn die zusätzliche Einschaltbedingung # aus dem Schlüssel "swoncond" im Consumer Attribut wahr ist @@ -13317,7 +13355,8 @@ sub lastConsumerSwitchtime { my $rswstate = ConsumerVal ($hash, $c, 'rswstate', 'state'); # Reading mit Schaltstatus my $swtime = ReadingsTimestamp ($dswname, $rswstate, ''); # Zeitstempel im Format 2016-02-16 19:34:24 - my $swtimets = timestringToTimestamp ($swtime) if($swtime); # Unix Timestamp Format erzeugen + my $swtimets; + $swtimets = timestringToTimestamp ($swtime) if($swtime); # Unix Timestamp Format erzeugen return ($swtime, $swtimets); } @@ -13602,10 +13641,7 @@ sub userExit { return if(!$uefn); $uefn =~ s/\s*#.*//g; # Kommentare entfernen - - my $r; - - $uefn = join ' ', split(/\s+/sx, $uefn); # Funktion aus Attr ctrlUserExitFn serialisieren + $uefn = join ' ', split(/\s+/sx, $uefn); # Funktion aus Attr ctrlUserExitFn serialisieren if ($uefn =~ m/^\s*(\{.*\})\s*$/xs) { # unnamed Funktion direkt in ctrlUserExitFn mit {...} $uefn = $1; @@ -15196,7 +15232,7 @@ to ensure that the system configuration is correct. [notbefore=<Hour>] [notafter=<Hour>] [locktime=<offlt>[:<onlt>]]
[auto=<Readingname>] [pcurr=<Readingname>:<Unit>[:<Threshold>]] [etotal=<Readingname>:<Einheit>[:<Threshold>]]
[swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>] [spignorecond=<Device>:<Reading>:<Regex>]
- [interruptable=<Option>]
+ [interruptable=<Option>] [noshow=<Option>]

Registers a consumer <Device Name> with the SolarForecast Device. In this case, <Device Name> @@ -15245,17 +15281,22 @@ to ensure that the system configuration is correct. noSchedule - there is no scheduling or automatic switching for the consumer.                        Display functions or manual switching are available. + power nominal power consumption of the consumer (see data sheet) in W (can be set to "0") + switchdev The specified <device> is assigned to the consumer as a switch device (optional). Switching operations are performed with this device. The key is useful for consumers where energy measurement and switching is carried out with different devices e.g. Homematic or readingsProxy. If switchdev is specified, the keys on, off, swstate and asynchronous refer to this device. + mode Consumer planning mode (optional). Allowed are: can - Scheduling takes place at the time when there is probably enough PV surplus available (default).          The consumer is not started at the time of planning if the PV surplus is insufficient. must - The consumer is optimally planned, even if there will probably not be enough PV surplus.            The consumer is started even if there is insufficient PV surplus. + icon Icon to represent the consumer in the overview graphic (optional) + mintime Scheduling duration (minutes or "SunPath") of the consumer. (optional) By specifying SunPath, planning is done according to sunrise and sunset. @@ -15273,36 +15314,48 @@ to ensure that the system configuration is correct. - other: 60 minutes on Set command for switching on the consumer (optional) + off Set command for switching off the consumer (optional) + swstate Reading which indicates the switching status of the consumer (default: 'state'). on-Regex - regular expression for the state 'on' (default: 'on') off-Regex - regular expression for the state 'off' (default: 'off') + asynchron the type of switching status determination in the consumer device. The status of the consumer is only determined after a switching command . by polling within a data collection interval (synchronous) or additionally by event processing (asynchronous). 0 - only synchronous processing of switching states (default) 1 - additional asynchronous processing of switching states through event processing + notbefore Schedule start time consumer not before specified hour (01..23) (optional) + notafter Schedule start time consumer not after specified hour (01..23) (optional) + auto Reading in the consumer device which enables or blocks the switching of the consumer (optional) Reading value = 1 - switching enabled (default), 0: switching blocked + pcurr Reading:Unit (W/kW) which provides the current energy consumption (optional) :<Threshold> (W) - From this power reference on, the consumer is considered active. The specification is optional (default: 0) + etotal Reading:Unit (Wh/kWh) of the consumer device that supplies the sum of the consumed energy (optional) :<Threshold> (Wh) - From this energy consumption per hour, the consumption is considered valid. Optional specification (default: 0) + swoncond Condition that must also be fulfilled in order to switch on the consumer (optional). The scheduled cycle is started. Device - Device to supply the additional switch-on condition Reading - Reading for delivery of the additional switch-on condition Regex - regular expression that must be satisfied for a 'true' condition to be true + swoffcond priority condition to switch off the consumer (optional). The scheduled cycle is stopped. Device - Device to supply the priority switch-off condition Reading - Reading for the delivery of the priority switch-off condition Regex - regular expression that must be satisfied for a 'true' condition to be true + spignorecond Condition to ignore a missing PV surplus (optional). If the condition is fulfilled, the load is switched on according to the planning even if there is no PV surplus at the time. CAUTION: Using both keys spignorecond and interruptable can lead to undesired behaviour! Device - Device to deliver the condition Reading - Reading which contains the condition Regex - regular expression that must be satisfied for a 'true' condition to be true + interruptable defines the possible interruption options for the consumer after it has been started (optional) 0 - Load is not temporarily switched off even if the PV surplus falls below the required energy (default) 1 - Load is temporarily switched off if the PV surplus falls below the required energy @@ -15312,11 +15365,19 @@ to ensure that the system configuration is correct. PV surplus provided (if power is not 0). The optional hysteresis is a numerical value by which the switch-off point is raised if the evaluated reading value is also numeric. (default: 0) + locktime Blocking times in seconds for switching the consumer (optional). offlt - Blocking time in seconds after the consumer has been switched off or interrupted onlt - Blocking time in seconds after the consumer has been switched on or continued The consumer is only switched again when the corresponding blocking time has elapsed. Note: The 'locktime' switch is only effective in automatic mode. + + noshow Hide or show consumers in graphic (optional). + 0 - the consumer is displayed (default) + 1 - the consumer is hidden + [Device:]Reading - Reading in the consumer or optionally an alternative device. + If the reading has the value "0" or is not present, the consumer is displayed. + If the reading has the value "1", the consumer is hidden.
@@ -15329,7 +15390,7 @@ to ensure that the system configuration is correct. attr <name> consumer04 Shelly.shellyplug3 icon=scene_microwave_oven type=heater power=2000 mode=must notbefore=07 mintime=600 on=on off=off etotal=relay_0_energy_Wh:Wh pcurr=relay_0_power:W auto=automatic interruptable=eg.wz.wandthermostat:diff-temp:(22)(\.[2-9])|([2-9][3-9])(\.[0-9]):0.2
attr <name> consumer05 Shelly.shellyplug4 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath interruptable=1
attr <name> consumer06 Shelly.shellyplug5 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath:60:-120 interruptable=1
- attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1
+ attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1 noshow=noShow

@@ -15708,7 +15769,8 @@ to ensure that the system configuration is correct.
  • graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ...
    Display of any reading values of the device. The values to be displayed are separated by spaces. Each value is to be defined by a label and the corresponding reading connected by ":". - The input can be multiline. Spaces in the label are to be inserted by "&nbsp;". + The input can be multiline. Spaces in the label are to be inserted by "&nbsp;", a line break + by "<br>".

      @@ -16981,7 +17043,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. [notbefore=<Stunde>] [notafter=<Stunde>] [locktime=<offlt>[:<onlt>]]
      [auto=<Readingname>] [pcurr=<Readingname>:<Einheit>[:<Schwellenwert>]] [etotal=<Readingname>:<Einheit>[:<Schwellenwert>]]
      [swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>] [spignorecond=<Device>:<Reading>:<Regex>]
      - [interruptable=<Option>]
      + [interruptable=<Option>] [noshow=<Option>]

      Registriert einen Verbraucher <Device Name> beim SolarForecast Device. Dabei ist <Device Name> @@ -17029,17 +17091,22 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. noSchedule - für den Verbraucher erfolgt keine Einplanung oder automatische Schaltung.                        Anzeigefunktionen oder manuelle Schaltungen sind verfügbar. + power nominale Leistungsaufnahme des Verbrauchers (siehe Datenblatt) in W (kann auf "0" gesetzt werden) + switchdev Das angegebene <device> wird als Schalter Device dem Verbraucher zugeordnet (optional). Schaltvorgänge werden mit diesem Gerät ausgeführt. Der Schlüssel ist für Verbraucher nützlich bei denen Energiemessung und Schaltung mit verschiedenen Geräten vorgenommen wird, z.B. Homematic oder readingsProxy. Ist switchdev angegeben, beziehen sich die Schlüssel on, off, swstate und asynchron auf dieses Gerät. + mode Planungsmodus des Verbrauchers (optional). Erlaubt sind: can - Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuß (default)          Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuß. must - der Verbraucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuß vorhanden sein wird            Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuß. + icon Icon zur Darstellung des Verbrauchers in der Übersichtsgrafik (optional) + mintime Einplanungsdauer (Minuten oder "SunPath") des Verbrauchers. (optional) Mit der Angabe von SunPath erfolgt die Planung entsprechend des Sonnenauf- und untergangs. @@ -17057,36 +17124,48 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. - other: 60 Minuten on Set-Kommando zum Einschalten des Verbrauchers (optional) + off Set-Kommando zum Ausschalten des Verbrauchers (optional) + swstate Reading welches den Schaltzustand des Verbrauchers anzeigt (default: 'state'). on-Regex - regulärer Ausdruck für den Zustand 'ein' (default: 'on') off-Regex - regulärer Ausdruck für den Zustand 'aus' (default: 'off') + asynchron die Art der Schaltstatus Ermittlung im Verbraucher Device. Die Statusermittlung des Verbrauchers nach einem Schaltbefehl erfolgt nur durch Abfrage innerhalb eines Datensammelintervals (synchron) oder zusätzlich durch Eventverarbeitung (asynchron). 0 - ausschließlich synchrone Verarbeitung von Schaltzuständen (default) 1 - zusätzlich asynchrone Verarbeitung von Schaltzuständen durch Eventverarbeitung + notbefore Startzeitpunkt Verbraucher nicht vor angegebener Stunde (01..23) einplanen (optional) + notafter Startzeitpunkt Verbraucher nicht nach angegebener Stunde (01..23) einplanen (optional) + auto Reading im Verbraucherdevice welches das Schalten des Verbrauchers freigibt bzw. blockiert (optional) Readingwert = 1 - Schalten freigegeben (default), 0: Schalten blockiert + pcurr Reading:Einheit (W/kW) welches den aktuellen Energieverbrauch liefert (optional) :<Schwellenwert> (W) - Ab diesem Leistungsbezug wird der Verbraucher als aktiv gewertet. Die Angabe ist optional (default: 0) + etotal Reading:Einheit (Wh/kWh) des Consumer Device, welches die Summe der verbrauchten Energie liefert (optional) :<Schwellenwert> (Wh) - Ab diesem Energieverbrauch pro Stunde wird der Verbrauch als gültig gewertet. Optionale Angabe (default: 0) + swoncond Bedingung die zusätzlich erfüllt sein muß um den Verbraucher einzuschalten (optional). Der geplante Zyklus wird gestartet. Device - Device zur Lieferung der zusätzlichen Einschaltbedingung Reading - Reading zur Lieferung der zusätzlichen Einschaltbedingung Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + swoffcond vorrangige Bedingung um den Verbraucher auszuschalten (optional). Der geplante Zyklus wird gestoppt. Device - Device zur Lieferung der vorrangigen Ausschaltbedingung Reading - Reading zur Lieferung der vorrangigen Ausschaltbedingung Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + spignorecond Bedingung um einen fehlenden PV Überschuß zu ignorieren (optional). Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuß vorliegt. ACHTUNG: Die Verwendung beider Schlüssel spignorecond und interruptable kann zu einem unerwünschten Verhalten führen! Device - Device zur Lieferung der Bedingung Reading - Reading welches die Bedingung enthält Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß + interruptable definiert die möglichen Unterbrechungsoptionen für den Verbraucher nachdem er gestartet wurde (optional) 0 - Verbraucher wird nicht temporär ausgeschaltet auch wenn der PV Überschuß die benötigte Energie unterschreitet (default) 1 - Verbraucher wird temporär ausgeschaltet falls der PV Überschuß die benötigte Energie unterschreitet @@ -17096,11 +17175,19 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. PV Überschuß (wenn power ungleich 0) vorliegt. Die optionale Hysterese ist ein numerischer Wert um den der Ausschaltpunkt gegenüber dem Soll-Einschaltpunkt angehoben wird sofern der ausgewertete Readingwert ebenfalls numerisch ist. (default: 0) + locktime Sperrzeiten in Sekunden für die Schaltung des Verbrauchers (optional). offlt - Sperrzeit in Sekunden nachdem der Verbraucher ausgeschaltet oder unterbrochen wurde onlt - Sperrzeit in Sekunden nachdem der Verbraucher eingeschaltet oder fortgesetzt wurde Der Verbraucher wird erst wieder geschaltet wenn die entsprechende Sperrzeit abgelaufen ist. Hinweis: Der Schalter 'locktime' ist nur im Automatik-Modus wirksam. + + noshow Verbraucher in Grafik ausblenden oder einblenden (optional). + 0 - der Verbraucher wird eingeblendet (default) + 1 - der Verbraucher wird ausgeblendet + [Device:]Reading - Reading im Verbraucher oder optional einem alternativen Device. + Hat das Reading den Wert "0" oder ist nicht vorhanden, wird der Verbraucher eingeblendet. + Hat das Reading den Wert "1", wird der Verbraucher ausgeblendet.

    @@ -17113,7 +17200,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden. attr <name> consumer04 Shelly.shellyplug3 icon=scene_microwave_oven type=heater power=2000 mode=must notbefore=07 mintime=600 on=on off=off etotal=relay_0_energy_Wh:Wh pcurr=relay_0_power:W auto=automatic interruptable=eg.wz.wandthermostat:diff-temp:(22)(\.[2-9])|([2-9][3-9])(\.[0-9]):0.2
    attr <name> consumer05 Shelly.shellyplug4 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath interruptable=1
    attr <name> consumer06 Shelly.shellyplug5 icon=sani_buffer_electric_heater_side type=heater mode=must power=1000 notbefore=7 notafter=20 auto=automatic pcurr=actpow:W on=on off=off mintime=SunPath:60:-120 interruptable=1
    - attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1
    + attr <name> consumer07 SolCastDummy icon=sani_buffer_electric_heater_side type=heater mode=can power=600 auto=automatic pcurr=actpow:W on=on off=off mintime=15 asynchron=1 locktime=300:1200 interruptable=1 noshow=noShow

  • @@ -17493,7 +17580,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
  • graphicHeaderOwnspec <Label>:<Reading> <Label>:<Reading> ...
    Anzeige beliebiger Readingswerte des Devices. Die anzuzeigenden Werte werden durch Leerzeichen getrennt. Jeder Wert ist jeweils durch ein Label und das dazugehörige Reading verbunden durch ":" zu definieren. - Die Eingabe kann mehrzeilig erfolgen. Leerzeichen im Label sind durch "&nbsp;" einzufügen. + Die Eingabe kann mehrzeilig erfolgen. Leerzeichen im Label sind durch "&nbsp;" einzufügen, ein Zeilenumbruch + durch "<br>".