From 85bba302330b03c03f48606241d08514d866532a Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sun, 3 Jul 2022 08:01:57 +0000 Subject: [PATCH] 76_SolarForecast.pm: contrib 0.65.0 git-svn-id: https://svn.fhem.de/fhem/trunk@26190 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/76_SolarForecast.pm | 192 ++++++++++++++------ 1 file changed, 141 insertions(+), 51 deletions(-) diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm index 91f58d4d2..e04eae3f2 100644 --- a/fhem/contrib/DS_Starter/76_SolarForecast.pm +++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm @@ -120,6 +120,7 @@ BEGIN { # Versions History intern my %vNotesIntern = ( + "0.65.0 "=> "03.07.2022 feature key interruptable for consumer ", "0.64.2 "=> "23.06.2022 fix switch off by switch off condition in ___switchConsumerOff ", "0.64.1 "=> "07.06.2022 fixing simplifyCstate, sub ___setConsumerSwitchingState to improve safe consumer switching ", "0.64.0 "=> "04.06.2022 consumer type charger added, new attr createConsumptionRecReadings ", @@ -3432,11 +3433,11 @@ sub __setConsRcmdState { my $type = $hash->{TYPE}; - my $surplus = CurrentVal ($hash, "surplus", 0); # aktueller Energieüberschuß - my $power = ConsumerVal ($hash, $c, "power", 0); # Consumer nominale Leistungsaufnahme (W) - my $ccr = AttrVal ($name, 'createConsumptionRecReadings', ''); # Liste der Consumer für die ConsumptionRecommended-Readings erstellt werden sollen + my $surplus = CurrentVal ($hash, "surplus", 0); # aktueller Energieüberschuß + my $nompower = ConsumerVal ($hash, $c, "power", 0); # Consumer nominale Leistungsaufnahme (W) + my $ccr = AttrVal ($name, 'createConsumptionRecReadings', ''); # Liste der Consumer für die ConsumptionRecommended-Readings erstellt werden sollen - if ($surplus >= $power) { + if ($surplus >= $nompower) { $data{$type}{$name}{consumers}{$c}{isConsumptionRecommended} = 1; # Einschalten des Consumers günstig } else { @@ -3535,6 +3536,24 @@ sub ___switchConsumerOn { Log3 ($name, 2, "$name - $state (Automatic = $auto)"); } } + elsif (isInterruptible($hash, $c) && isConsRcmd ($hash, $c) && # unterbrochenen Consumer fortsetzen + isInTimeframe ($hash, $c) && simplifyCstate ($pstate) =~ /interrupted|interrupting/xs && + $auto && $oncom) { + + CommandSet(undef,"$cname $oncom"); + + $paref->{ps} = "continuing:"; + + ___setConsumerPlanningState ($paref); + + delete $paref->{ps}; + + $state = qq{switching Consumer "$calias" to "$oncom", caution: continuing by surplus}; + + writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + Log3 ($name, 2, "$name - $state"); + } return $state; } @@ -3573,7 +3592,7 @@ sub ___switchConsumerOff { if(($swoffcond || ($stopts && $t >= $stopts)) && ($auto && $offcom && simplifyCstate($pstate) =~ /started|starting|stopping/xs)) { CommandSet(undef,"$cname $offcom"); - $paref->{ps} = "switching off:"; + $paref->{ps} = "switching off:"; ___setConsumerPlanningState ($paref); @@ -3582,10 +3601,28 @@ sub ___switchConsumerOff { my $caution = $swoffcond ? "switch-off condition (key swoffcond) is true" : "planned switch-off time reached/exceeded"; $state = qq{switching Consumer "$calias" to "$offcom", caution: $caution}; - writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben Log3 ($name, 2, "$name - $state (Automatic = $auto)"); } + elsif (isInterruptible($hash, $c) && !isConsRcmd ($hash, $c) && # Consumer unterbrechen + isInTimeframe ($hash, $c) && simplifyCstate ($pstate) =~ /started|continued|interrupting/xs && + $auto && $offcom) { + + CommandSet(undef,"$cname $offcom"); + + $paref->{ps} = "interrupting:"; + + ___setConsumerPlanningState ($paref); + + delete $paref->{ps}; + + $state = qq{switching Consumer "$calias" to "$offcom", caution: surplus shortage}; + + writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + Log3 ($name, 2, "$name - $state"); + } return $state; } @@ -3645,6 +3682,32 @@ sub ___setConsumerSwitchingState { Log3 ($name, 2, "$name - $state (Automatic = $auto)"); } + elsif ($pstate eq 'continuing' && isConsumerPhysOn ($hash, $c)) { + $paref->{ps} = "continued:"; + + ___setConsumerPlanningState ($paref); + + delete $paref->{ps}; + + $state = qq{Consumer "$calias" switched on (continued)}; + + writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + Log3 ($name, 2, "$name - $state"); + } + elsif ($pstate eq 'interrupting' && isConsumerPhysOff ($hash, $c)) { + $paref->{ps} = "interrupted:"; + + ___setConsumerPlanningState ($paref); + + delete $paref->{ps}; + + $state = qq{Consumer "$calias" switched off (interrupted)}; + + writeDataToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben + + Log3 ($name, 2, "$name - $state"); + } return $state; } @@ -3666,7 +3729,7 @@ sub __remainConsumerTime { $data{$type}{$name}{consumers}{$c}{remainTime} = 0; - if (isInTimeframe($hash, $c) && $planstate eq "started" && isConsumerPhysOn($hash, $c)) { + if (isInTimeframe($hash, $c) && (($planstate =~ /started/xs && isConsumerPhysOn($hash, $c)) | $planstate =~ /interrupt|continu/xs)) { my $remainTime = $stopts - $t ; $data{$type}{$name}{consumers}{$c}{remainTime} = sprintf "%.0f", ($remainTime / 60) if($remainTime > 0); } @@ -4368,7 +4431,12 @@ sub collectAllRegConsumers { my ($dswoffcond,$rswoffcond,$swoffcondregex); if(exists $hc->{swoffcond}) { # vorrangige Ausschaltbedingung ($dswoffcond,$rswoffcond,$swoffcondregex) = split ":", $hc->{swoffcond}; - } + } + + my $interruptable = 0; + if(exists $hc->{interruptable}) { + $interruptable = 1 if($hc->{interruptable} ne '0'); + } my $rauto = $hc->{auto} // q{}; my $ctype = $hc->{type} // $defctype; @@ -4406,6 +4474,7 @@ sub collectAllRegConsumers { $data{$type}{$name}{consumers}{$c}{dswoffcond} = $dswoffcond // q{}; # Device zur Lieferung einer vorrangigen Ausschaltbedingung $data{$type}{$name}{consumers}{$c}{rswoffcond} = $rswoffcond // q{}; # Reading zur Lieferung einer vorrangigen Ausschaltbedingung $data{$type}{$name}{consumers}{$c}{swoffcondregex} = $swoffcondregex // q{}; # Regex einer vorrangigen Ausschaltbedingung + $data{$type}{$name}{consumers}{$c}{interruptable} = $interruptable; # Ein-Zustand des Verbrauchers ist unterbrechbar } Log3 ($name, 5, "$name - all registered consumers:\n".Dumper $data{$type}{$name}{consumers}); @@ -7488,6 +7557,16 @@ sub isConsRcmd { return ConsumerVal ($hash, $c, 'isConsumptionRecommended', 0); } +################################################################ +# ist Consumer $c unterbrechbar (1) oder nicht (0) +################################################################ +sub isInterruptible { + my $hash = shift; + my $c = shift; + +return ConsumerVal ($hash, $c, 'interruptable', 0); +} + ################################################################ # liefert die Zeit des letzten Schaltvorganges ################################################################ @@ -7517,12 +7596,16 @@ return ($swtime, $swtimets); sub simplifyCstate { my $ps = shift; - $ps = $ps =~ /planned/xs ? 'planned' : - $ps =~ /switching\son/xs ? 'starting' : - $ps =~ /switched\son/xs ? 'started' : - $ps =~ /switching\soff/xs ? 'stopping' : - $ps =~ /switched\soff/xs ? 'finished' : - $ps =~ /priority/xs ? 'priority' : + $ps = $ps =~ /planned/xs ? 'planned' : + $ps =~ /switching\son/xs ? 'starting' : + $ps =~ /switched\son/xs ? 'started' : + $ps =~ /switching\soff/xs ? 'stopping' : + $ps =~ /switched\soff/xs ? 'finished' : + $ps =~ /priority/xs ? 'priority' : + $ps =~ /interrupting/xs ? 'interrupting' : + $ps =~ /interrupted/xs ? 'interrupted' : + $ps =~ /continuing/xs ? 'continuing' : + $ps =~ /continued/xs ? 'continued' : "unknown"; return $ps; @@ -7768,6 +7851,7 @@ return $def; # rswoffcond - Reading zur Lieferung einer vorrangige Ausschaltbedingung # swoffcondregex - Regex einer einer vorrangige Ausschaltbedingung # isIntimeframe - ist Zeit innerhalb der Planzeit ein/aus +# interruptable - Consumer "on" ist während geplanter "ein"-Zeit unterbrechbar # # $def: Defaultwert # @@ -8536,7 +8620,7 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
  • consumerXX <Device Name> type=<type> power=<power> [mode=<mode>] [icon=<Icon>] [mintime=<minutes>]
    [on=<Kommando>] [off=<Kommando>] [swstate=<Readingname>:<on-Regex>:<off-Regex>] [notbefore=<Stunde>] [notafter=<Stunde>]
    [auto=<Readingname>] [pcurr=<Readingname>:<Einheit>[:<Schwellenwert>]] [etotal=<Readingname>:<Einheit>[:<Schwellenwert>]]
    - [swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>]


    + [swoncond=<Device>:<Reading>:<Regex>] [swoffcond=<Device>:<Reading>:<Regex>] [interruptable=0|1]

    Registriert einen Verbraucher <Device Name> beim SolarForecast Device. Dabei ist <Device Name> ein in FHEM bereits angelegtes Verbraucher Device, z.B. eine Schaltsteckdose. @@ -8554,45 +8638,51 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen Der optionale Schlüssel swoffcond definiert eine vorrangige Ausschaltbedingung (Regex). Sobald diese Bedingung erfüllt ist, wird der Consumer ausgeschaltet auch wenn die geplante Endezeit (consumerXX_planned_stop) noch nicht erreicht ist (ODER-Verknüpfung). Weitere Bedingungen wie off-Schlüssel und auto-Mode müssen - zum automatischen Ausschalten erfüllt sein. + zum automatischen Ausschalten erfüllt sein.

    + + Mit dem optionalen Schlüssel interruptable kann während der geplanten Einschaltzeit eine automatische + Unterbrechung sowie Wiedereinschaltung des Verbrauchers vorgenommen werden. Unterschreitet der PV Überschuß + die benötigte Energie, wird der Verbraucher ausgeschaltet (interrupted) und eingeschaltet wenn wieder + ausreichend PV Überschuß vorhanden ist (continued). Die verbleibende Laufzeit wird durch einen Interrupt nicht beeinflusst !