mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 09:55:38 +00:00
76_SolarForecast: ctrlDebug consumerSwitching splitted into separated consumers, minor bug fix
git-svn-id: https://svn.fhem.de/fhem/trunk@28921 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
72e1929315
commit
dcc6f688b8
@ -1,5 +1,7 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||||
# Do not insert empty lines here, update check depends on it
|
# Do not insert empty lines here, update check depends on it
|
||||||
|
- change: 76_SolarForecast: ctrlDebug consumerSwitching splitted into
|
||||||
|
separated consumers, minor bug fix
|
||||||
- feature: 74_AutomowerConnect: new design attribute hideSchedulerButton
|
- feature: 74_AutomowerConnect: new design attribute hideSchedulerButton
|
||||||
- change: 76_SolarForecast: VictronVRM - API request start time adopted
|
- change: 76_SolarForecast: VictronVRM - API request start time adopted
|
||||||
- change: 73_GardenaSmartBridge: fix: api call,rate limit
|
- change: 73_GardenaSmartBridge: fix: api call,rate limit
|
||||||
|
@ -157,6 +157,9 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.21.3" => "27.05.2024 __getCyclesAndRuntime: change procedure determine consumer runtime and cycles per day ".
|
||||||
|
"__calcPVestimates: correct printout 'Estimated PV generation (calc)' and '(raw)' ".
|
||||||
|
"ctrlDebug: consumerSwitching splitted into separated consumers ",
|
||||||
"1.21.2" => "26.05.2024 __VictronVRM_ApiRequestForecast: change request time from current time to '<current hour>:00:00'",
|
"1.21.2" => "26.05.2024 __VictronVRM_ApiRequestForecast: change request time from current time to '<current hour>:00:00'",
|
||||||
"1.21.1" => "23.05.2024 new sub isDeviceValid, replace Smartmatch Forum:#137776 ",
|
"1.21.1" => "23.05.2024 new sub isDeviceValid, replace Smartmatch Forum:#137776 ",
|
||||||
"1.21.0" => "14.05.2024 currentMeterDev: meter can be a Day meter, contotal and feedtotal can be reset at day begin ",
|
"1.21.0" => "14.05.2024 currentMeterDev: meter can be a Day meter, contotal and feedtotal can be reset at day begin ",
|
||||||
@ -248,7 +251,7 @@ my %vNotesIntern = (
|
|||||||
"1.6.4" => "09.01.2024 fix get Automatic State, use key switchdev for auto-Reading if switchdev is set in consumer attr ",
|
"1.6.4" => "09.01.2024 fix get Automatic State, use key switchdev for auto-Reading if switchdev is set in consumer attr ",
|
||||||
"1.6.3" => "08.01.2024 optimize battery management once more ",
|
"1.6.3" => "08.01.2024 optimize battery management once more ",
|
||||||
"1.6.2" => "07.01.2024 optimize battery management ",
|
"1.6.2" => "07.01.2024 optimize battery management ",
|
||||||
"1.6.1" => "04.01.2024 new sub __setPhysSwState, edit ___setConsumerPlanningState, boost performance of _collectAllRegConsumers ".
|
"1.6.1" => "04.01.2024 new sub __setPhysLogSwState, edit ___setConsumerPlanningState, boost performance of _collectAllRegConsumers ".
|
||||||
"CurrentVal ctrunning - Central Task running Statusbit, edit comref ",
|
"CurrentVal ctrunning - Central Task running Statusbit, edit comref ",
|
||||||
"1.6.0" => "22.12.2023 store daily batmaxsoc in pvHistory, new attr ctrlBatSocManagement, reading Battery_OptimumTargetSoC ".
|
"1.6.0" => "22.12.2023 store daily batmaxsoc in pvHistory, new attr ctrlBatSocManagement, reading Battery_OptimumTargetSoC ".
|
||||||
"currentBatteryDev: new optional key 'cap', adapt cloud2bin,temp2bin,rain2bin ".
|
"currentBatteryDev: new optional key 'cap', adapt cloud2bin,temp2bin,rain2bin ".
|
||||||
@ -456,15 +459,13 @@ my $cssdef = qq{.flowg.text { stroke: none; fill: gray; font-size: 60p
|
|||||||
;
|
;
|
||||||
|
|
||||||
# mögliche Debug-Module
|
# mögliche Debug-Module
|
||||||
my @dd = qw( none
|
my @dd = qw( aiProcess
|
||||||
aiProcess
|
|
||||||
aiData
|
aiData
|
||||||
apiCall
|
apiCall
|
||||||
apiProcess
|
apiProcess
|
||||||
batteryManagement
|
batteryManagement
|
||||||
collectData
|
collectData
|
||||||
consumerPlanning
|
consumerPlanning
|
||||||
consumerSwitching
|
|
||||||
consumption
|
consumption
|
||||||
dwdComm
|
dwdComm
|
||||||
epiecesCalc
|
epiecesCalc
|
||||||
@ -519,11 +520,11 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo
|
|||||||
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
|
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
|
||||||
);
|
);
|
||||||
|
|
||||||
for my $cinit (1..$maxconsumer) { # Anlagenkonfiguration: add Consumer Attribute
|
for my $cinit (1..$maxconsumer) {
|
||||||
$cinit = sprintf "%02d", $cinit;
|
$cinit = sprintf "%02d", $cinit;
|
||||||
my $consumer = "consumer${cinit}";
|
push @aconfigs, "consumer${cinit}"; # Anlagenkonfiguration: add Consumer Attribute
|
||||||
push @aconfigs, $consumer;
|
push @dd, "consumerSwitching${cinit}"; # ctrlDebug: add specific Consumer
|
||||||
}
|
}
|
||||||
|
|
||||||
my $allwidgets = 'icon|sortable|uzsu|knob|noArg|time|text|slider|multiple|select|bitfield|widgetList|colorpicker';
|
my $allwidgets = 'icon|sortable|uzsu|knob|noArg|time|text|slider|multiple|select|bitfield|widgetList|colorpicker';
|
||||||
|
|
||||||
@ -595,6 +596,7 @@ my %hattr = ( # H
|
|||||||
consumer => { fn => \&_attrconsumer },
|
consumer => { fn => \&_attrconsumer },
|
||||||
ctrlConsRecommendReadings => { fn => \&_attrcreateConsRecRdgs },
|
ctrlConsRecommendReadings => { fn => \&_attrcreateConsRecRdgs },
|
||||||
ctrlStatisticReadings => { fn => \&_attrcreateStatisticRdgs },
|
ctrlStatisticReadings => { fn => \&_attrcreateStatisticRdgs },
|
||||||
|
ctrlDebug => { fn => \&_attrctrlDebug },
|
||||||
ctrlWeatherDev1 => { fn => \&_attrWeatherDev },
|
ctrlWeatherDev1 => { fn => \&_attrWeatherDev },
|
||||||
ctrlWeatherDev2 => { fn => \&_attrWeatherDev },
|
ctrlWeatherDev2 => { fn => \&_attrWeatherDev },
|
||||||
ctrlWeatherDev3 => { fn => \&_attrWeatherDev },
|
ctrlWeatherDev3 => { fn => \&_attrWeatherDev },
|
||||||
@ -1113,7 +1115,7 @@ sub Initialize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $allcs = join ",", @allc;
|
my $allcs = join ",", @allc;
|
||||||
my $dm = join ",", @dd;
|
my $dm = 'none,'.join ",", sort @dd;
|
||||||
|
|
||||||
$hash->{DefFn} = \&Define;
|
$hash->{DefFn} = \&Define;
|
||||||
$hash->{UndefFn} = \&Undef;
|
$hash->{UndefFn} = \&Undef;
|
||||||
@ -5637,6 +5639,34 @@ sub _attrcreateStatisticRdgs { ## no critic "not used"
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# Attr ctrlDebug
|
||||||
|
################################################################
|
||||||
|
sub _attrctrlDebug { ## no critic "not used"
|
||||||
|
my $paref = shift;
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $aName = $paref->{aName};
|
||||||
|
my $aVal = $paref->{aVal};
|
||||||
|
|
||||||
|
my $te = 'consumerSwitching';
|
||||||
|
|
||||||
|
if ($aVal =~ /$te/xs && $init_done) {
|
||||||
|
my @aa = split ",", $aVal;
|
||||||
|
|
||||||
|
for my $elm (@aa) {
|
||||||
|
next if($elm !~ /$te/xs);
|
||||||
|
$elm =~ /([0-9]{2})/xs; # Consumer Nummer filetieren
|
||||||
|
|
||||||
|
if (!AttrVal ($name, 'consumer'.$1, '')) {
|
||||||
|
return qq{The consumer 'consumer$1' is currently not registered as an active consumer!};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Attr ctrlWeatherDevX
|
# Attr ctrlWeatherDevX
|
||||||
################################################################
|
################################################################
|
||||||
@ -6830,10 +6860,6 @@ sub _specialActivities {
|
|||||||
|
|
||||||
if ($t > $planswitchoff && $simpCstat =~ /planned|finished|unknown/xs) {
|
if ($t > $planswitchoff && $simpCstat =~ /planned|finished|unknown/xs) {
|
||||||
deleteConsumerPlanning ($hash, $c);
|
deleteConsumerPlanning ($hash, $c);
|
||||||
|
|
||||||
$data{$type}{$name}{consumers}{$c}{minutesOn} = 0;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{numberDayStarts} = 0;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{onoff} = 'off';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6920,12 +6946,7 @@ sub _specialActivities {
|
|||||||
|
|
||||||
for my $c (keys %{$data{$type}{$name}{consumers}}) { # Planungsdaten regulär löschen
|
for my $c (keys %{$data{$type}{$name}{consumers}}) { # Planungsdaten regulär löschen
|
||||||
next if(ConsumerVal ($hash, $c, "plandelete", "regular") ne "regular");
|
next if(ConsumerVal ($hash, $c, "plandelete", "regular") ne "regular");
|
||||||
|
|
||||||
deleteConsumerPlanning ($hash, $c);
|
deleteConsumerPlanning ($hash, $c);
|
||||||
|
|
||||||
$data{$type}{$name}{consumers}{$c}{minutesOn} = 0;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{numberDayStarts} = 0;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{onoff} = 'off';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben
|
writeCacheToFile ($hash, "consumers", $csmcache.$name); # Cache File Consumer schreiben
|
||||||
@ -7655,14 +7676,16 @@ sub __calcPVestimates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$peak *= 1000;
|
$peak *= 1000;
|
||||||
my $est = SolCastAPIVal ($hash, $string, $wantdt, 'pv_estimate50', 0) * $hc; # Korrekturfaktor anwenden
|
my $est = SolCastAPIVal ($hash, $string, $wantdt, 'pv_estimate50', 0);
|
||||||
my $pv = sprintf "%.1f", $est;
|
my $pv = sprintf "%.1f", ($est * $hc); # Korrekturfaktor anwenden
|
||||||
|
|
||||||
if ($debug =~ /radiationProcess/xs) {
|
if ($debug =~ /radiationProcess/xs) {
|
||||||
$lh = { # Log-Hash zur Ausgabe
|
$lh = { # Log-Hash zur Ausgabe
|
||||||
"modulePeakString" => $peak. " W",
|
"modulePeakString" => $peak. " W",
|
||||||
"Estimated PV generation (raw)" => $est. " Wh",
|
"Estimated PV generation (raw)" => $est. " Wh",
|
||||||
"Estimated PV generation (calc)" => $pv. " Wh",
|
"Estimated PV generation (calc)" => $pv. " Wh",
|
||||||
|
"PV correction factor" => $hc,
|
||||||
|
"PV correction quality" => $hq,
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($acu =~ /on_complex/xs) {
|
if ($acu =~ /on_complex/xs) {
|
||||||
@ -7706,8 +7729,6 @@ sub __calcPVestimates {
|
|||||||
"Cloudcover" => $cloudcover,
|
"Cloudcover" => $cloudcover,
|
||||||
"Total Rain last hour" => $totalrain." kg/m2",
|
"Total Rain last hour" => $totalrain." kg/m2",
|
||||||
"PV Correction mode" => ($acu ? $acu : 'no'),
|
"PV Correction mode" => ($acu ? $acu : 'no'),
|
||||||
"PV correction factor" => $hc,
|
|
||||||
"PV correction quality" => $hq,
|
|
||||||
"PV generation forecast" => $pvsum." Wh ".$logao,
|
"PV generation forecast" => $pvsum." Wh ".$logao,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -8658,7 +8679,6 @@ sub _manageConsumerData {
|
|||||||
my $name = $paref->{name};
|
my $name = $paref->{name};
|
||||||
my $type = $paref->{type};
|
my $type = $paref->{type};
|
||||||
my $t = $paref->{t}; # aktuelle Zeit
|
my $t = $paref->{t}; # aktuelle Zeit
|
||||||
my $date = $paref->{date}; # aktuelles Datum
|
|
||||||
my $chour = $paref->{chour};
|
my $chour = $paref->{chour};
|
||||||
my $day = $paref->{day};
|
my $day = $paref->{day};
|
||||||
|
|
||||||
@ -8666,6 +8686,7 @@ sub _manageConsumerData {
|
|||||||
$paref->{nhour} = sprintf "%02d", $nhour;
|
$paref->{nhour} = sprintf "%02d", $nhour;
|
||||||
|
|
||||||
for my $c (sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}) {
|
for my $c (sort{$a<=>$b} keys %{$data{$type}{$name}{consumers}}) {
|
||||||
|
$paref->{consumer} = $c;
|
||||||
my $consumer = ConsumerVal ($hash, $c, "name", "");
|
my $consumer = ConsumerVal ($hash, $c, "name", "");
|
||||||
my $alias = ConsumerVal ($hash, $c, "alias", "");
|
my $alias = ConsumerVal ($hash, $c, "alias", "");
|
||||||
|
|
||||||
@ -8731,55 +8752,11 @@ sub _manageConsumerData {
|
|||||||
|
|
||||||
deleteReadingspec ($hash, "consumer${c}_currentPower") if(!$etotread && !$paread);
|
deleteReadingspec ($hash, "consumer${c}_currentPower") if(!$etotread && !$paread);
|
||||||
|
|
||||||
## Verbraucher - Laufzeit und Zyklen pro Tag ermitteln
|
|
||||||
## Laufzeit (in Minuten) wird pro Stunde erfasst
|
|
||||||
## bei Tageswechsel Rücksetzen in _specialActivities
|
|
||||||
#######################################################
|
|
||||||
my $starthour;
|
|
||||||
if (isConsumerLogOn ($hash, $c, $pcurr)) { # Verbraucher ist logisch "an"
|
|
||||||
if (ConsumerVal ($hash, $c, "onoff", "off") eq "off") {
|
|
||||||
$data{$type}{$name}{consumers}{$c}{onoff} = 'on';
|
|
||||||
$data{$type}{$name}{consumers}{$c}{startTime} = $t; # startTime ist nicht von "Automatic" abhängig -> nicht identisch mit planswitchon !!!
|
|
||||||
$data{$type}{$name}{consumers}{$c}{cycleStarttime} = $t;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{cycleTime} = 0;
|
|
||||||
my $stimes = ConsumerVal ($hash, $c, "numberDayStarts", 0); # Anzahl der On-Schaltungen am Tag
|
|
||||||
$data{$type}{$name}{consumers}{$c}{numberDayStarts} = $stimes+1;
|
|
||||||
$data{$type}{$name}{consumers}{$c}{lastMinutesOn} = ConsumerVal ($hash, $c, "minutesOn", 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$data{$type}{$name}{consumers}{$c}{cycleTime} = (($t - ConsumerVal ($hash, $c, 'cycleStarttime', $t)) / 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, "startTime", $t));
|
|
||||||
|
|
||||||
if ($chour eq $starthour) {
|
|
||||||
my $runtime = (($t - ConsumerVal ($hash, $c, "startTime", $t)) / 60); # in Minuten ! (gettimeofday sind ms !)
|
|
||||||
$data{$type}{$name}{consumers}{$c}{minutesOn} = ConsumerVal ($hash, $c, "lastMinutesOn", 0) + $runtime;
|
|
||||||
}
|
|
||||||
else { # neue Stunde hat begonnen
|
|
||||||
if (ConsumerVal ($hash, $c, "onoff", "off") eq 'on') {
|
|
||||||
$data{$type}{$name}{consumers}{$c}{startTime} = timestringToTimestamp ($date." ".sprintf("%02d", $chour).":00:00");
|
|
||||||
$data{$type}{$name}{consumers}{$c}{minutesOn} = ($t - ConsumerVal ($hash, $c, "startTime", $t)) / 60; # in Minuten ! (gettimeofday sind ms !)
|
|
||||||
$data{$type}{$name}{consumers}{$c}{lastMinutesOn} = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { # Verbraucher soll nicht aktiv sein
|
|
||||||
$data{$type}{$name}{consumers}{$c}{onoff} = 'off';
|
|
||||||
$data{$type}{$name}{consumers}{$c}{cycleTime} = 0;
|
|
||||||
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, "startTime", $t));
|
|
||||||
|
|
||||||
if ($chour ne $starthour) {
|
|
||||||
$data{$type}{$name}{consumers}{$c}{minutesOn} = 0;
|
|
||||||
delete $data{$type}{$name}{consumers}{$c}{startTime};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$paref->{val} = ConsumerVal ($hash, $c, "numberDayStarts", 0); # Anzahl Tageszyklen des Verbrauchers speichern
|
$paref->{val} = ConsumerVal ($hash, $c, "numberDayStarts", 0); # Anzahl Tageszyklen des Verbrauchers speichern
|
||||||
$paref->{histname} = "cyclescsm${c}";
|
$paref->{histname} = "cyclescsm${c}";
|
||||||
setPVhistory ($paref);
|
setPVhistory ($paref);
|
||||||
|
|
||||||
$paref->{val} = ceil ConsumerVal ($hash, $c, "minutesOn", 0); # Verbrauchsminuten akt. Stunde des Consumers
|
$paref->{val} = ceil ConsumerVal ($hash, $c, "minutesOn", 0); # Verbrauchsminuten akt. Stunde des Consumers speichern
|
||||||
$paref->{histname} = "minutescsm${c}";
|
$paref->{histname} = "minutescsm${c}";
|
||||||
setPVhistory ($paref);
|
setPVhistory ($paref);
|
||||||
|
|
||||||
@ -8813,7 +8790,6 @@ sub _manageConsumerData {
|
|||||||
$data{$type}{$name}{consumers}{$c}{avgruntime} = sprintf "%.2f", (($runhours / $dnum) * 60); # Durchschnittslaufzeit am Tag in Minuten
|
$data{$type}{$name}{consumers}{$c}{avgruntime} = sprintf "%.2f", (($runhours / $dnum) * 60); # Durchschnittslaufzeit am Tag in Minuten
|
||||||
}
|
}
|
||||||
|
|
||||||
$paref->{consumer} = $c;
|
|
||||||
|
|
||||||
__getAutomaticState ($paref); # Automatic Status des Consumers abfragen
|
__getAutomaticState ($paref); # Automatic Status des Consumers abfragen
|
||||||
__calcEnergyPieces ($paref); # Energieverbrauch auf einzelne Stunden für Planungsgrundlage aufteilen
|
__calcEnergyPieces ($paref); # Energieverbrauch auf einzelne Stunden für Planungsgrundlage aufteilen
|
||||||
@ -8821,18 +8797,23 @@ sub _manageConsumerData {
|
|||||||
__setTimeframeState ($paref); # Timeframe Status ermitteln
|
__setTimeframeState ($paref); # Timeframe Status ermitteln
|
||||||
__setConsRcmdState ($paref); # Consumption Recommended Status setzen
|
__setConsRcmdState ($paref); # Consumption Recommended Status setzen
|
||||||
__switchConsumer ($paref); # Consumer schalten
|
__switchConsumer ($paref); # Consumer schalten
|
||||||
|
|
||||||
|
$paref->{pcurr} = $pcurr;
|
||||||
|
|
||||||
|
__getCyclesAndRuntime ($paref); # Verbraucher - Laufzeit, Tagesstarts und Aktivminuten pro Stunde ermitteln
|
||||||
|
__setPhysLogSwState ($paref); # physischen / logischen Schaltzustand festhalten
|
||||||
__reviewSwitchTime ($paref); # Planungsdaten überprüfen und ggf. neu planen
|
__reviewSwitchTime ($paref); # Planungsdaten überprüfen und ggf. neu planen
|
||||||
__remainConsumerTime ($paref); # Restlaufzeit Verbraucher ermitteln
|
__remainConsumerTime ($paref); # Restlaufzeit Verbraucher ermitteln
|
||||||
__setPhysSwState ($paref); # physischen Schaltzustand festhalten
|
|
||||||
|
delete $paref->{pcurr};
|
||||||
|
|
||||||
## Consumer Schaltstatus und Schaltzeit für Readings ermitteln
|
## Consumer Schaltstatus und Schaltzeit für Readings ermitteln
|
||||||
################################################################
|
################################################################
|
||||||
my $costate = isConsumerPhysOn ($hash, $c) ? "on" :
|
my $costate = isConsumerPhysOn ($hash, $c) ? 'on' :
|
||||||
isConsumerPhysOff ($hash, $c) ? "off" :
|
isConsumerPhysOff ($hash, $c) ? 'off' :
|
||||||
"unknown";
|
"unknown";
|
||||||
|
|
||||||
$data{$type}{$name}{consumers}{$c}{state} = $costate;
|
$data{$type}{$name}{consumers}{$c}{state} = $costate;
|
||||||
|
|
||||||
my ($pstate,$starttime,$stoptime,$supplmnt) = __getPlanningStateAndTimes ($paref);
|
my ($pstate,$starttime,$stoptime,$supplmnt) = __getPlanningStateAndTimes ($paref);
|
||||||
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
||||||
my $mode = ConsumerVal ($hash, $c, 'mode', 'can');
|
my $mode = ConsumerVal ($hash, $c, 'mode', 'can');
|
||||||
@ -9760,23 +9741,23 @@ sub ___switchConsumerOn {
|
|||||||
|
|
||||||
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
||||||
|
|
||||||
if ($debug =~ /consumerSwitching/x) { # nur für Debugging
|
if ($debug =~ /consumerSwitching${c}/x) { # nur für Debugging
|
||||||
my $cons = CurrentVal ($hash, 'consumption', 0);
|
my $cons = CurrentVal ($hash, 'consumption', 0);
|
||||||
my $nompow = ConsumerVal ($hash, $c, 'power', '-');
|
my $nompow = ConsumerVal ($hash, $c, 'power', '-');
|
||||||
my $sp = CurrentVal ($hash, 'surplus', 0);
|
my $sp = CurrentVal ($hash, 'surplus', 0);
|
||||||
|
|
||||||
Log3 ($name, 1, qq{$name DEBUG> ############### consumerSwitching consumer "$c" ############### });
|
Log3 ($name, 1, qq{$name DEBUG> ############### consumerSwitching consumer "$c" ###############});
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - general switching parameters => }.
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - general switching parameters => }.
|
||||||
qq{auto mode: $auto, current Consumption: $cons W, nompower: $nompow, surplus: $sp W, }.
|
qq{auto mode: $auto, Current household consumption: $cons W, nompower: $nompow, surplus: $sp W, }.
|
||||||
qq{planstate: $pstate, starttime: }.($startts ? (timestampToTimestring ($startts, $lang))[0] : "undef")
|
qq{planstate: $pstate, starttime: }.($startts ? (timestampToTimestring ($startts, $lang))[0] : "undef")
|
||||||
);
|
);
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isInLocktime: $iilt}.($rlt ? ", remainLockTime: $rlt seconds" : ''));
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isInLocktime: $iilt}.($rlt ? ", remainLockTime: $rlt seconds" : ''));
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - current Context is >switch on< => }.
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - in Context 'switch on' => }.
|
||||||
qq{swoncond: $swoncond, on-command: $oncom }
|
qq{swoncond: $swoncond, on-command: $oncom }
|
||||||
);
|
);
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isAddSwitchOnCond Info: $infon}) if($swoncond && $infon);
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isAddSwitchOnCond Info: $infon}) if($swoncond && $infon);
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isAddSwitchOffCond Info: $infoff}) if($swoffcond && $infoff);
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - isAddSwitchOffCond Info: $infoff}) if($swoffcond && $infoff);
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - device >$dswname< is used as switching device});
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - device '$dswname' is used as switching device});
|
||||||
|
|
||||||
if ($simpCstat =~ /planned|priority|starting|continuing/xs && $isInTime && $iilt) {
|
if ($simpCstat =~ /planned|priority|starting|continuing/xs && $isInTime && $iilt) {
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - switching on postponed by >isInLocktime<});
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - switching on postponed by >isInLocktime<});
|
||||||
@ -9801,7 +9782,7 @@ sub ___switchConsumerOn {
|
|||||||
my $mode = ConsumerVal ($hash, $c, "mode", $defcmode); # Consumer Planungsmode
|
my $mode = ConsumerVal ($hash, $c, "mode", $defcmode); # Consumer Planungsmode
|
||||||
my $enable = ___enableSwitchByBatPrioCharge ($paref); # Vorrangladung Batterie ?
|
my $enable = ___enableSwitchByBatPrioCharge ($paref); # Vorrangladung Batterie ?
|
||||||
|
|
||||||
debugLog ($paref, "consumerSwitching", qq{$name DEBUG> Consumer switch enable by battery state: $enable});
|
debugLog ($paref, "consumerSwitching${c}", qq{$name DEBUG> Consumer switch enable by battery state: $enable});
|
||||||
|
|
||||||
if ($mode eq "can" && !$enable) { # Batterieladung - keine Verbraucher "Einschalten" Freigabe
|
if ($mode eq "can" && !$enable) { # Batterieladung - keine Verbraucher "Einschalten" Freigabe
|
||||||
$paref->{ps} = "priority charging battery";
|
$paref->{ps} = "priority charging battery";
|
||||||
@ -9876,8 +9857,8 @@ sub ___switchConsumerOff {
|
|||||||
|
|
||||||
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
my ($iilt,$rlt) = isInLocktime ($paref); # Sperrzeit Status ermitteln
|
||||||
|
|
||||||
if ($debug =~ /consumerSwitching/x) { # nur für Debugging
|
if ($debug =~ /consumerSwitching${c}/x) { # nur für Debugging
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - current Context is >switch off< => }.
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - in Context 'switch off' => }.
|
||||||
qq{swoffcond: $swoffcond, off-command: $offcom}
|
qq{swoffcond: $swoffcond, off-command: $offcom}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -9944,7 +9925,7 @@ sub ___setConsumerSwitchingState {
|
|||||||
my $oldpsw = ConsumerVal ($hash, $c, 'physoffon', 'off'); # gespeicherter physischer Schaltzustand
|
my $oldpsw = ConsumerVal ($hash, $c, 'physoffon', 'off'); # gespeicherter physischer Schaltzustand
|
||||||
my $dowri = 0;
|
my $dowri = 0;
|
||||||
|
|
||||||
debugLog ($paref, "consumerSwitching", qq{consumer "$c" - current planning state: $simpCstat \n});
|
debugLog ($paref, "consumerSwitching${c}", qq{consumer "$c" - current planning state: $simpCstat});
|
||||||
|
|
||||||
if (isConsumerPhysOn ($hash, $c) && $simpCstat eq 'starting') {
|
if (isConsumerPhysOn ($hash, $c) && $simpCstat eq 'starting') {
|
||||||
my $mintime = ConsumerVal ($hash, $c, "mintime", $defmintime);
|
my $mintime = ConsumerVal ($hash, $c, "mintime", $defmintime);
|
||||||
@ -10038,6 +10019,92 @@ sub ___setConsumerSwitchingState {
|
|||||||
return $state;
|
return $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
## Verbraucher - Laufzeit, Tagesstarts und Aktivminuten pro
|
||||||
|
## Stunde ermitteln
|
||||||
|
## Tageswechsel Management
|
||||||
|
################################################################
|
||||||
|
sub __getCyclesAndRuntime {
|
||||||
|
my $paref = shift;
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
|
my $t = $paref->{t};
|
||||||
|
my $chour = $paref->{chour};
|
||||||
|
my $day = $paref->{day}; # aktueller Tag (range 01 to 31)
|
||||||
|
my $date = $paref->{date}; # aktuelles Datum
|
||||||
|
my $pcurr = $paref->{pcurr};
|
||||||
|
my $c = $paref->{consumer};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
|
my ($startday, $starthour);
|
||||||
|
|
||||||
|
if (isConsumerLogOn ($hash, $c, $pcurr)) { # Verbraucher ist logisch "an"
|
||||||
|
if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'off') {
|
||||||
|
$data{$type}{$name}{consumers}{$c}{onoff} = 'on';
|
||||||
|
$data{$type}{$name}{consumers}{$c}{startTime} = $t; # startTime ist nicht von "Automatic" abhängig -> nicht identisch mit planswitchon !!!
|
||||||
|
$data{$type}{$name}{consumers}{$c}{cycleStarttime} = $t;
|
||||||
|
$data{$type}{$name}{consumers}{$c}{cycleTime} = 0;
|
||||||
|
#my $stimes = ConsumerVal ($hash, $c, 'numberDayStarts', 0); # Anzahl der On-Schaltungen am Tag
|
||||||
|
$data{$type}{$name}{consumers}{$c}{numberDayStarts}++;
|
||||||
|
$data{$type}{$name}{consumers}{$c}{lastMinutesOn} = ConsumerVal ($hash, $c, 'minutesOn', 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$data{$type}{$name}{consumers}{$c}{cycleTime} = (($t - ConsumerVal ($hash, $c, 'cycleStarttime', $t)) / 60); # Minuten
|
||||||
|
}
|
||||||
|
|
||||||
|
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', $t));
|
||||||
|
$startday = strftime "%d", localtime(ConsumerVal ($hash, $c, 'startTime', $t)); # aktueller Tag (range 01 to 31)
|
||||||
|
|
||||||
|
if ($chour eq $starthour) {
|
||||||
|
my $runtime = (($t - ConsumerVal ($hash, $c, 'startTime', $t)) / 60); # in Minuten ! (gettimeofday sind ms !)
|
||||||
|
$data{$type}{$name}{consumers}{$c}{minutesOn} = ConsumerVal ($hash, $c, 'lastMinutesOn', 0) + $runtime;
|
||||||
|
}
|
||||||
|
else { # neue Stunde hat begonnen
|
||||||
|
if (ConsumerVal ($hash, $c, 'onoff', 'off') eq 'on') {
|
||||||
|
$data{$type}{$name}{consumers}{$c}{startTime} = timestringToTimestamp ($date.' '.sprintf("%02d", $chour).':00:00');
|
||||||
|
$data{$type}{$name}{consumers}{$c}{minutesOn} = ($t - ConsumerVal ($hash, $c, 'startTime', $t)) / 60; # in Minuten ! (gettimeofday sind ms !)
|
||||||
|
$data{$type}{$name}{consumers}{$c}{lastMinutesOn} = 0;
|
||||||
|
|
||||||
|
if ($day ne $startday) { # Tageswechsel
|
||||||
|
$data{$type}{$name}{consumers}{$c}{numberDayStarts} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { # Verbraucher soll nicht aktiv sein
|
||||||
|
$data{$type}{$name}{consumers}{$c}{onoff} = 'off';
|
||||||
|
#$data{$type}{$name}{consumers}{$c}{cycleTime} = 0;
|
||||||
|
$starthour = strftime "%H", localtime(ConsumerVal ($hash, $c, 'startTime', $t));
|
||||||
|
$startday = strftime "%d", localtime(ConsumerVal ($hash, $c, 'startTime', $t));
|
||||||
|
|
||||||
|
if ($chour ne $starthour) {
|
||||||
|
$data{$type}{$name}{consumers}{$c}{minutesOn} = 0;
|
||||||
|
delete $data{$type}{$name}{consumers}{$c}{startTime};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($day ne $startday) { # Tageswechsel
|
||||||
|
$data{$type}{$name}{consumers}{$c}{numberDayStarts} = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($debug =~ /consumerSwitching${c}/xs) {
|
||||||
|
my $sr = 'still running';
|
||||||
|
my $son = isConsumerLogOn ($hash, $c, $pcurr) ? $sr : ConsumerVal ($hash, $c, 'cycleTime', 0) * 60; # letzte Cycle-Zeitdauer in Sekunden
|
||||||
|
my $cst = ConsumerVal ($hash, $c, 'cycleStarttime', 0);
|
||||||
|
$son = $son && $son ne $sr ? timestampToTimestring ($cst + $son, $paref->{lang}) :
|
||||||
|
$son eq $sr ? $sr :
|
||||||
|
'-';
|
||||||
|
$cst = $cst ? timestampToTimestring ($cst, $paref->{lang}) : '-';
|
||||||
|
|
||||||
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - numberDayStarts: }.ConsumerVal ($hash, $c, 'numberDayStarts', 0));
|
||||||
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - last cycle start time: $cst});
|
||||||
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - last cycle end time: $son});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Restlaufzeit Verbraucher ermitteln
|
# Restlaufzeit Verbraucher ermitteln
|
||||||
################################################################
|
################################################################
|
||||||
@ -10050,7 +10117,7 @@ sub __remainConsumerTime {
|
|||||||
my $t = $paref->{t}; # aktueller Unixtimestamp
|
my $t = $paref->{t}; # aktueller Unixtimestamp
|
||||||
|
|
||||||
my ($planstate,$startstr,$stoptstr) = __getPlanningStateAndTimes ($paref);
|
my ($planstate,$startstr,$stoptstr) = __getPlanningStateAndTimes ($paref);
|
||||||
my $stopts = ConsumerVal ($hash, $c, "planswitchoff", undef); # geplante Unix Stopzeit
|
my $stopts = ConsumerVal ($hash, $c, 'planswitchoff', undef); # geplante Unix Stopzeit
|
||||||
|
|
||||||
$data{$type}{$name}{consumers}{$c}{remainTime} = 0;
|
$data{$type}{$name}{consumers}{$c}{remainTime} = 0;
|
||||||
|
|
||||||
@ -10063,18 +10130,27 @@ return;
|
|||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Consumer physischen Schaltstatus setzen
|
# Consumer physischen & logischen Schaltstatus setzen
|
||||||
################################################################
|
################################################################
|
||||||
sub __setPhysSwState {
|
sub __setPhysLogSwState {
|
||||||
my $paref = shift;
|
my $paref = shift;
|
||||||
my $hash = $paref->{hash};
|
my $hash = $paref->{hash};
|
||||||
my $name = $paref->{name};
|
my $name = $paref->{name};
|
||||||
my $type = $paref->{type};
|
my $type = $paref->{type};
|
||||||
my $c = $paref->{consumer};
|
my $c = $paref->{consumer};
|
||||||
|
my $pcurr = $paref->{pcurr};
|
||||||
|
my $debug = $paref->{debug};
|
||||||
|
|
||||||
my $pon = isConsumerPhysOn ($hash, $c) ? 'on' : 'off';
|
my $cpo = isConsumerPhysOn ($hash, $c) ? 'on' : 'off';
|
||||||
|
my $clo = isConsumerLogOn ($hash, $c, $pcurr) ? 'on' : 'off';
|
||||||
|
|
||||||
$data{$type}{$name}{consumers}{$c}{physoffon} = $pon;
|
$data{$type}{$name}{consumers}{$c}{physoffon} = $cpo;
|
||||||
|
$data{$type}{$name}{consumers}{$c}{logoffon} = $clo;
|
||||||
|
|
||||||
|
if ($debug =~ /consumerSwitching${c}/xs) {
|
||||||
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - physical Switchstate: $cpo});
|
||||||
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - logical Switchstate: $clo \n});
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -16305,7 +16381,7 @@ sub isAddSwitchOffCond {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$info .= qq{-> the effect depends on the switch context\n};
|
$info .= qq{-> the effect depends on the switch context};
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($swoff, $info, $err);
|
return ($swoff, $info, $err);
|
||||||
@ -16342,7 +16418,7 @@ sub isSurplusIgnoCond {
|
|||||||
my $spignorecondregex = ConsumerVal ($hash, $c, 'spignorecondregex', ''); # Regex einer zusätzliche Einschaltbedingung
|
my $spignorecondregex = ConsumerVal ($hash, $c, 'spignorecondregex', ''); # Regex einer zusätzliche Einschaltbedingung
|
||||||
my $condval = ReadingsVal ($digncond, $rigncond, ''); # Wert zum Vergleich mit Regex
|
my $condval = ReadingsVal ($digncond, $rigncond, ''); # Wert zum Vergleich mit Regex
|
||||||
|
|
||||||
if ($condval && $debug =~ /consumerSwitching/x) {
|
if ($condval && $debug =~ /consumerSwitching${c}/x) {
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - PV surplus ignore condition ist set - device: $digncond, reading: $rigncond, condition: $spignorecondregex});
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - PV surplus ignore condition ist set - device: $digncond, reading: $rigncond, condition: $spignorecondregex});
|
||||||
}
|
}
|
||||||
@ -16453,7 +16529,7 @@ sub isInterruptable {
|
|||||||
my ($swoffcond,$info,$err) = isAddSwitchOffCond ($hash, $c, $intable, $hyst);
|
my ($swoffcond,$info,$err) = isAddSwitchOffCond ($hash, $c, $intable, $hyst);
|
||||||
Log3 ($name, 1, "$name - $err") if($err);
|
Log3 ($name, 1, "$name - $err") if($err);
|
||||||
|
|
||||||
if ($print && $debug =~ /consumerSwitching/x) {
|
if ($print && $debug =~ /consumerSwitching${c}/x) {
|
||||||
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - Interrupt Info: $info});
|
Log3 ($name, 1, qq{$name DEBUG> consumer "$c" - Interrupt Info: $info});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17707,6 +17783,7 @@ return $def;
|
|||||||
# oncom - Einschaltkommando
|
# oncom - Einschaltkommando
|
||||||
# offcom - Ausschaltkommando
|
# offcom - Ausschaltkommando
|
||||||
# physoffon - physischer Schaltzustand ein/aus
|
# physoffon - physischer Schaltzustand ein/aus
|
||||||
|
# logoffon - logischer Schaltzustand ein/aus
|
||||||
# onoff - logischer ein/aus Zustand des am Consumer angeschlossenen Endverbrauchers
|
# onoff - logischer ein/aus Zustand des am Consumer angeschlossenen Endverbrauchers
|
||||||
# asynchron - Arbeitsweise des FHEM Consumer Devices
|
# asynchron - Arbeitsweise des FHEM Consumer Devices
|
||||||
# retotal - Reading der Leistungsmessung
|
# retotal - Reading der Leistungsmessung
|
||||||
@ -19388,7 +19465,7 @@ to ensure that the system configuration is correct.
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<table>
|
<table>
|
||||||
<colgroup> <col width="23%"> <col width="77%"> </colgroup>
|
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||||
<tr><td> <b>aiProcess</b> </td><td>Data enrichment and training process for AI support </td></tr>
|
<tr><td> <b>aiProcess</b> </td><td>Data enrichment and training process for AI support </td></tr>
|
||||||
<tr><td> <b>aiData</b> </td><td>Data use AI in the forecasting process </td></tr>
|
<tr><td> <b>aiData</b> </td><td>Data use AI in the forecasting process </td></tr>
|
||||||
<tr><td> <b>apiCall</b> </td><td>Retrieval API interface without data output </td></tr>
|
<tr><td> <b>apiCall</b> </td><td>Retrieval API interface without data output </td></tr>
|
||||||
@ -19396,7 +19473,7 @@ to ensure that the system configuration is correct.
|
|||||||
<tr><td> <b>batteryManagement</b> </td><td>Battery management control values (SoC) </td></tr>
|
<tr><td> <b>batteryManagement</b> </td><td>Battery management control values (SoC) </td></tr>
|
||||||
<tr><td> <b>collectData</b> </td><td>detailed data collection </td></tr>
|
<tr><td> <b>collectData</b> </td><td>detailed data collection </td></tr>
|
||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer scheduling processes </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operations of the internal consumer switching module </td></tr>
|
<tr><td> <b>consumerSwitchingXX</b> </td><td>Operations of the internal consumer switching module of consumer XX </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Consumption calculation and use </td></tr>
|
||||||
<tr><td> <b>dwdComm</b> </td><td>Communication with the website or server of the German Weather Service (DWD) </td></tr>
|
<tr><td> <b>dwdComm</b> </td><td>Communication with the website or server of the German Weather Service (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Calculation of specific energy consumption per operating hour and consumer </td></tr>
|
||||||
@ -21672,7 +21749,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<table>
|
<table>
|
||||||
<colgroup> <col width="23%"> <col width="77%"> </colgroup>
|
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||||
<tr><td> <b>aiProcess</b> </td><td>Datenanreicherung und Trainingsprozess der KI Unterstützung </td></tr>
|
<tr><td> <b>aiProcess</b> </td><td>Datenanreicherung und Trainingsprozess der KI Unterstützung </td></tr>
|
||||||
<tr><td> <b>aiData</b> </td><td>Datennutzung KI im Prognoseprozess </td></tr>
|
<tr><td> <b>aiData</b> </td><td>Datennutzung KI im Prognoseprozess </td></tr>
|
||||||
<tr><td> <b>apiCall</b> </td><td>Abruf API Schnittstelle ohne Datenausgabe </td></tr>
|
<tr><td> <b>apiCall</b> </td><td>Abruf API Schnittstelle ohne Datenausgabe </td></tr>
|
||||||
@ -21680,7 +21757,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<tr><td> <b>batteryManagement</b> </td><td>Steuerungswerte des Batterie Managements (SoC) </td></tr>
|
<tr><td> <b>batteryManagement</b> </td><td>Steuerungswerte des Batterie Managements (SoC) </td></tr>
|
||||||
<tr><td> <b>collectData</b> </td><td>detailliierte Datensammlung </td></tr>
|
<tr><td> <b>collectData</b> </td><td>detailliierte Datensammlung </td></tr>
|
||||||
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
<tr><td> <b>consumerPlanning</b> </td><td>Consumer Einplanungsprozesse </td></tr>
|
||||||
<tr><td> <b>consumerSwitching</b> </td><td>Operationen des internen Consumer Schaltmodul </td></tr>
|
<tr><td> <b>consumerSwitchingXX</b> </td><td>Operationen des internen Consumer Schaltmodul für Verbraucher XX </td></tr>
|
||||||
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
<tr><td> <b>consumption</b> </td><td>Verbrauchskalkulation und -nutzung </td></tr>
|
||||||
<tr><td> <b>dwdComm</b> </td><td>Kommunikation mit Webseite oder Server des Deutschen Wetterdienst (DWD) </td></tr>
|
<tr><td> <b>dwdComm</b> </td><td>Kommunikation mit Webseite oder Server des Deutschen Wetterdienst (DWD) </td></tr>
|
||||||
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
<tr><td> <b>epiecesCalc</b> </td><td>Berechnung des spezifischen Energieverbrauchs je Betriebsstunde und Verbraucher </td></tr>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user