mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-28 11:01:59 +00:00
76_SolarForecast: contrib 1.36.0
git-svn-id: https://svn.fhem.de/fhem/trunk@29224 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
eeae8a4786
commit
ddd8b252c1
@ -156,6 +156,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.36.0" => "11.10.2024 new Getter valInverter, preparation for multiple inverters ",
|
||||||
"1.35.0" => "09.10.2024 _flowGraphic: replace inverter icon by FHEM SVG-Icon (sun/moon), sun or icon of moon phases according ".
|
"1.35.0" => "09.10.2024 _flowGraphic: replace inverter icon by FHEM SVG-Icon (sun/moon), sun or icon of moon phases according ".
|
||||||
"day/night new optional key 'icon' in attr setupInverterDev, resize all flowgraphic icons to a standard ".
|
"day/night new optional key 'icon' in attr setupInverterDev, resize all flowgraphic icons to a standard ".
|
||||||
"scaling, __switchConsumer: run ___setConsumerSwitchingState before switch subs ".
|
"scaling, __switchConsumer: run ___setConsumerSwitchingState before switch subs ".
|
||||||
@ -433,6 +434,8 @@ my $tempbasedef = 25;
|
|||||||
|
|
||||||
my $maxconsumer = 16; # maximale Anzahl der möglichen Consumer (Attribut)
|
my $maxconsumer = 16; # maximale Anzahl der möglichen Consumer (Attribut)
|
||||||
my $maxproducer = 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
my $maxproducer = 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
||||||
|
my $maxinverter = 1; # maximale Anzahl der möglichen Inverter
|
||||||
|
|
||||||
my $epiecMaxCycles = 10; # Anzahl Einschaltzyklen (Consumer) für verbraucherspezifische Energiestück Ermittlung
|
my $epiecMaxCycles = 10; # Anzahl Einschaltzyklen (Consumer) für verbraucherspezifische Energiestück Ermittlung
|
||||||
my @ctypes = qw(dishwasher dryer washingmachine heater charger other
|
my @ctypes = qw(dishwasher dryer washingmachine heater charger other
|
||||||
noSchedule); # erlaubte Consumer Typen
|
noSchedule); # erlaubte Consumer Typen
|
||||||
@ -540,7 +543,6 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo
|
|||||||
ctrlLanguage ctrlNextDayForecastReadings ctrlShowLink ctrlSolCastAPImaxReq
|
ctrlLanguage ctrlNextDayForecastReadings ctrlShowLink ctrlSolCastAPImaxReq
|
||||||
ctrlSolCastAPIoptimizeReq ctrlStatisticReadings ctrlUserExitFn
|
ctrlSolCastAPIoptimizeReq ctrlStatisticReadings ctrlUserExitFn
|
||||||
setupWeatherDev1 setupWeatherDev2 setupWeatherDev3
|
setupWeatherDev1 setupWeatherDev2 setupWeatherDev3
|
||||||
setupOtherProducer01 setupOtherProducer02 setupOtherProducer03
|
|
||||||
disable
|
disable
|
||||||
flowGraphicSize flowGraphicAnimate flowGraphicConsumerDistance flowGraphicShowConsumer
|
flowGraphicSize flowGraphicAnimate flowGraphicConsumerDistance flowGraphicShowConsumer
|
||||||
flowGraphicShowConsumerDummy flowGraphicShowConsumerPower flowGraphicShowConsumerRemainTime
|
flowGraphicShowConsumerDummy flowGraphicShowConsumerPower flowGraphicShowConsumerRemainTime
|
||||||
@ -553,7 +555,7 @@ my @aconfigs = qw( affect70percentRule affectBatteryPreferredCharge affectConsFo
|
|||||||
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
|
graphicHeaderDetail graphicHeaderShow graphicHistoryHour graphicHourCount graphicHourStyle
|
||||||
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
|
graphicLayoutType graphicSelect graphicShowDiff graphicShowNight graphicShowWeather
|
||||||
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
|
graphicSpaceSize graphicStartHtml graphicEndHtml graphicWeatherColor graphicWeatherColorNight
|
||||||
setupMeterDev setupBatteryDev setupInverterDev setupInverterStrings setupRadiationAPI setupStringPeak
|
setupMeterDev setupBatteryDev setupInverterStrings setupRadiationAPI setupStringPeak
|
||||||
setupRoofTops
|
setupRoofTops
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -563,6 +565,11 @@ for my $cinit (1..$maxconsumer) {
|
|||||||
push @dd, "consumerSwitching${cinit}"; # ctrlDebug: add specific Consumer
|
push @dd, "consumerSwitching${cinit}"; # ctrlDebug: add specific Consumer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
push @aconfigs, "setupInverterDev${in}"; # Anlagenkonfiguration: add Inverter Attribute
|
||||||
|
}
|
||||||
|
|
||||||
for my $prn (1..$maxproducer) {
|
for my $prn (1..$maxproducer) {
|
||||||
$prn = sprintf "%02d", $prn;
|
$prn = sprintf "%02d", $prn;
|
||||||
push @aconfigs, "setupOtherProducer${prn}"; # Anlagenkonfiguration: add Producer Attribute
|
push @aconfigs, "setupOtherProducer${prn}"; # Anlagenkonfiguration: add Producer Attribute
|
||||||
@ -614,6 +621,7 @@ my %hget = ( # Ha
|
|||||||
html => { fn => \&_gethtml, needcred => 0 },
|
html => { fn => \&_gethtml, needcred => 0 },
|
||||||
ftui => { fn => \&_getftui, needcred => 0 },
|
ftui => { fn => \&_getftui, needcred => 0 },
|
||||||
valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
|
valCurrent => { fn => \&_getlistCurrent, needcred => 0 },
|
||||||
|
valInverter => { fn => \&_getlistvalInverter, needcred => 0 },
|
||||||
valConsumerMaster => { fn => \&_getlistvalConsumerMaster, needcred => 0 },
|
valConsumerMaster => { fn => \&_getlistvalConsumerMaster, needcred => 0 },
|
||||||
plantConfigCheck => { fn => \&_setplantConfiguration, needcred => 0 },
|
plantConfigCheck => { fn => \&_setplantConfiguration, needcred => 0 },
|
||||||
pvHistory => { fn => \&_getlistPVHistory, needcred => 0 },
|
pvHistory => { fn => \&_getlistPVHistory, needcred => 0 },
|
||||||
@ -644,6 +652,11 @@ my %hattr = ( # H
|
|||||||
setupRoofTops => { fn => \&_attrRoofTops },
|
setupRoofTops => { fn => \&_attrRoofTops },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
$hattr{'setupInverterDev'.$in}{fn} = \&_attrInverterDev;
|
||||||
|
}
|
||||||
|
|
||||||
for my $prn (1..$maxproducer) {
|
for my $prn (1..$maxproducer) {
|
||||||
$prn = sprintf "%02d", $prn;
|
$prn = sprintf "%02d", $prn;
|
||||||
$hattr{'setupOtherProducer'.$prn}{fn} = \&_attrOtherProducer;
|
$hattr{'setupOtherProducer'.$prn}{fn} = \&_attrOtherProducer;
|
||||||
@ -683,8 +696,8 @@ my %hqtxt = (
|
|||||||
DE => qq{Bitte geben sie mindestens ein Wettervorhersage Device mit "attr LINK setupWeatherDev1" an} },
|
DE => qq{Bitte geben sie mindestens ein Wettervorhersage Device mit "attr LINK setupWeatherDev1" an} },
|
||||||
crd => { EN => qq{Please select the radiation forecast service with "attr LINK setupRadiationAPI"},
|
crd => { EN => qq{Please select the radiation forecast service with "attr LINK setupRadiationAPI"},
|
||||||
DE => qq{Bitte geben sie den Strahlungsvorhersage Dienst mit "attr LINK setupRadiationAPI" an} },
|
DE => qq{Bitte geben sie den Strahlungsvorhersage Dienst mit "attr LINK setupRadiationAPI" an} },
|
||||||
cid => { EN => qq{Please specify the Inverter device with "attr LINK setupInverterDev"},
|
cid => { EN => qq{Please specify the Inverter device with "attr LINK setupInverterDev01"},
|
||||||
DE => qq{Bitte geben sie das Wechselrichter Device mit "attr LINK setupInverterDev" an} },
|
DE => qq{Bitte geben sie das Wechselrichter Device mit "attr LINK setupInverterDev01" an} },
|
||||||
mid => { EN => qq{Please specify the device for energy measurement with "attr LINK setupMeterDev"},
|
mid => { EN => qq{Please specify the device for energy measurement with "attr LINK setupMeterDev"},
|
||||||
DE => qq{Bitte geben sie das Device zur Energiemessung mit "attr LINK setupMeterDev" an} },
|
DE => qq{Bitte geben sie das Device zur Energiemessung mit "attr LINK setupMeterDev" an} },
|
||||||
ist => { EN => qq{Please define all of your used string names with "attr LINK setupInverterStrings"},
|
ist => { EN => qq{Please define all of your used string names with "attr LINK setupInverterStrings"},
|
||||||
@ -1124,14 +1137,34 @@ my %hfspvh = (
|
|||||||
gfeedin => { fn => \&_storeVal, storname => 'gfeedin', validkey => undef, fpar => 'comp99' }, # eingespeiste Energie
|
gfeedin => { fn => \&_storeVal, storname => 'gfeedin', validkey => undef, fpar => 'comp99' }, # eingespeiste Energie
|
||||||
con => { fn => \&_storeVal, storname => 'con', validkey => undef, fpar => 'comp99' }, # realer Hausverbrauch Energie
|
con => { fn => \&_storeVal, storname => 'con', validkey => undef, fpar => 'comp99' }, # realer Hausverbrauch Energie
|
||||||
pvrl => { fn => \&_storeVal, storname => 'pvrl', validkey => 'pvrlvd', fpar => 'comp99' }, # realer Energieertrag PV
|
pvrl => { fn => \&_storeVal, storname => 'pvrl', validkey => 'pvrlvd', fpar => 'comp99' }, # realer Energieertrag PV
|
||||||
pprl01 => { fn => \&_storeVal, storname => 'pprl01', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 01
|
|
||||||
pprl02 => { fn => \&_storeVal, storname => 'pprl02', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 02
|
|
||||||
pprl03 => { fn => \&_storeVal, storname => 'pprl03', validkey => undef, fpar => 'comp99' }, # realer Energieertrag sonstiger Erzeuger 03
|
|
||||||
etotalp01 => { fn => \&_storeVal, storname => 'etotalp01', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 01
|
|
||||||
etotalp02 => { fn => \&_storeVal, storname => 'etotalp02', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 02
|
|
||||||
etotalp03 => { fn => \&_storeVal, storname => 'etotalp03', validkey => undef, fpar => undef }, # etotal sonstiger Erzeuger 03
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
$hfspvh{'pvrl'.$in}{fn} = \&_storeVal; # realer Energieertrag Inverter
|
||||||
|
$hfspvh{'pvrl'.$in}{storname} = 'pvrl'.$in;
|
||||||
|
$hfspvh{'pvrl'.$in}{validkey} = undef;
|
||||||
|
$hfspvh{'pvrl'.$in}{fpar} = 'comp99';
|
||||||
|
|
||||||
|
$hfspvh{'etotali'.$in}{fn} = \&_storeVal; # etotal Inverter
|
||||||
|
$hfspvh{'etotali'.$in}{storname} = 'etotali'.$in;
|
||||||
|
$hfspvh{'etotali'.$in}{validkey} = undef;
|
||||||
|
$hfspvh{'etotali'.$in}{fpar} = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
for my $pn (1..$maxproducer) {
|
||||||
|
$pn = sprintf "%02d", $pn;
|
||||||
|
$hfspvh{'pprl'.$pn}{fn} = \&_storeVal; # realer Energieertrag sonstiger Erzeuger
|
||||||
|
$hfspvh{'pprl'.$pn}{storname} = 'pprl'.$pn;
|
||||||
|
$hfspvh{'pprl'.$pn}{validkey} = undef;
|
||||||
|
$hfspvh{'pprl'.$pn}{fpar} = 'comp99';
|
||||||
|
|
||||||
|
$hfspvh{'etotalp'.$pn}{fn} = \&_storeVal; # etotal sonstiger Erzeuger
|
||||||
|
$hfspvh{'etotalp'.$pn}{storname} = 'etotalp'.$pn;
|
||||||
|
$hfspvh{'etotalp'.$pn}{validkey} = undef;
|
||||||
|
$hfspvh{'etotalp'.$pn}{fpar} = undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Information zu verwendeten internen Datenhashes
|
# Information zu verwendeten internen Datenhashes
|
||||||
# $data{$type}{$name}{circular} # Ringspeicher
|
# $data{$type}{$name}{circular} # Ringspeicher
|
||||||
@ -1140,6 +1173,7 @@ my %hfspvh = (
|
|||||||
# $data{$type}{$name}{pvhist} # historische Werte
|
# $data{$type}{$name}{pvhist} # historische Werte
|
||||||
# $data{$type}{$name}{nexthours} # NextHours Werte
|
# $data{$type}{$name}{nexthours} # NextHours Werte
|
||||||
# $data{$type}{$name}{consumers} # Consumer Hash
|
# $data{$type}{$name}{consumers} # Consumer Hash
|
||||||
|
# $data{$type}{$name}{inverters} # Inverter Hash
|
||||||
# $data{$type}{$name}{strings} # Stringkonfiguration Hash
|
# $data{$type}{$name}{strings} # Stringkonfiguration Hash
|
||||||
# $data{$type}{$name}{solcastapi} # Zwischenspeicher API-Daten
|
# $data{$type}{$name}{solcastapi} # Zwischenspeicher API-Daten
|
||||||
# $data{$type}{$name}{aidectree}{object} # AI Decision Tree Object
|
# $data{$type}{$name}{aidectree}{object} # AI Decision Tree Object
|
||||||
@ -1161,13 +1195,18 @@ sub Initialize {
|
|||||||
my $srd = join ",", sort keys (%hcsr);
|
my $srd = join ",", sort keys (%hcsr);
|
||||||
my $gbc = 'pvReal,pvForecast,consumption,consumptionForecast,gridconsumption,energycosts,gridfeedin,feedincome';
|
my $gbc = 'pvReal,pvForecast,consumption,consumptionForecast,gridconsumption,energycosts,gridfeedin,feedincome';
|
||||||
|
|
||||||
my ($consumer, $setupprod, @allc);
|
my ($consumer, $setupprod, $setupinv, @allc);
|
||||||
for my $c (1..$maxconsumer) {
|
for my $c (1..$maxconsumer) {
|
||||||
$c = sprintf "%02d", $c;
|
$c = sprintf "%02d", $c;
|
||||||
$consumer .= "consumer${c}:textField-long ";
|
$consumer .= "consumer${c}:textField-long ";
|
||||||
push @allc, $c;
|
push @allc, $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
$setupinv .= "setupInverterDev${in}:textField-long ";
|
||||||
|
}
|
||||||
|
|
||||||
for my $prn (1..$maxproducer) {
|
for my $prn (1..$maxproducer) {
|
||||||
$prn = sprintf "%02d", $prn;
|
$prn = sprintf "%02d", $prn;
|
||||||
$setupprod .= "setupOtherProducer${prn}:textField-long ";
|
$setupprod .= "setupOtherProducer${prn}:textField-long ";
|
||||||
@ -1258,7 +1297,6 @@ sub Initialize {
|
|||||||
"graphicEndHtml ".
|
"graphicEndHtml ".
|
||||||
"graphicWeatherColor:colorpicker,RGB ".
|
"graphicWeatherColor:colorpicker,RGB ".
|
||||||
"graphicWeatherColorNight:colorpicker,RGB ".
|
"graphicWeatherColorNight:colorpicker,RGB ".
|
||||||
"setupInverterDev:textField-long ".
|
|
||||||
"setupInverterStrings ".
|
"setupInverterStrings ".
|
||||||
"setupMeterDev:textField-long ".
|
"setupMeterDev:textField-long ".
|
||||||
"setupWeatherDev1 ".
|
"setupWeatherDev1 ".
|
||||||
@ -1268,6 +1306,7 @@ sub Initialize {
|
|||||||
"setupBatteryDev:textField-long ".
|
"setupBatteryDev:textField-long ".
|
||||||
"setupRadiationAPI ".
|
"setupRadiationAPI ".
|
||||||
"setupStringPeak ".
|
"setupStringPeak ".
|
||||||
|
$setupinv.
|
||||||
$setupprod.
|
$setupprod.
|
||||||
$consumer.
|
$consumer.
|
||||||
$readingFnAttributes;
|
$readingFnAttributes;
|
||||||
@ -1281,6 +1320,7 @@ sub Initialize {
|
|||||||
"ctrlWeatherDev1" => "setupWeatherDev1", # 20.08.24
|
"ctrlWeatherDev1" => "setupWeatherDev1", # 20.08.24
|
||||||
"ctrlWeatherDev2" => "setupWeatherDev2",
|
"ctrlWeatherDev2" => "setupWeatherDev2",
|
||||||
"ctrlWeatherDev3" => "setupWeatherDev3",
|
"ctrlWeatherDev3" => "setupWeatherDev3",
|
||||||
|
"setupInverterDev" => "setupInverterDev01", # 11.10.24
|
||||||
};
|
};
|
||||||
|
|
||||||
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval'
|
eval { FHEM::Meta::InitMod( __FILE__, $hash ) }; ## no critic 'eval'
|
||||||
@ -2425,13 +2465,16 @@ sub Get {
|
|||||||
|
|
||||||
my @pha = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$type}{$name}{pvhist}};
|
my @pha = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$type}{$name}{pvhist}};
|
||||||
my @vcm = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$type}{$name}{consumers}};
|
my @vcm = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$type}{$name}{consumers}};
|
||||||
|
my @vin = map {sprintf "%02d", $_} sort {$a<=>$b} keys %{$data{$type}{$name}{inverters}};
|
||||||
|
|
||||||
my $hol = join ",", @ho;
|
my $hol = join ",", @ho;
|
||||||
my $pvl = join ",", @pha;
|
my $pvl = join ",", @pha;
|
||||||
my $cml = join ",", @vcm;
|
my $cml = join ",", @vcm;
|
||||||
|
my $inl = join ",", @vin;
|
||||||
|
|
||||||
my $getlist = "Unknown argument $opt, choose one of ".
|
my $getlist = "Unknown argument $opt, choose one of ".
|
||||||
"valConsumerMaster:#,$cml ".
|
"valConsumerMaster:#,$cml ".
|
||||||
|
"valInverter:#,$inl ".
|
||||||
"data:noArg ".
|
"data:noArg ".
|
||||||
"dwdCatalog ".
|
"dwdCatalog ".
|
||||||
"forecastQualities:noArg ".
|
"forecastQualities:noArg ".
|
||||||
@ -4573,12 +4616,27 @@ sub _getlistvalConsumerMaster {
|
|||||||
my $arg = $paref->{arg};
|
my $arg = $paref->{arg};
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
|
|
||||||
my $ret = listDataPool ($hash, 'consumer', $arg);
|
my $ret = listDataPool ($hash, 'consumers', $arg);
|
||||||
$ret .= lineFromSpaces ($ret, 10);
|
$ret .= lineFromSpaces ($ret, 10);
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Getter valInverter
|
||||||
|
###############################################################
|
||||||
|
sub _getlistvalInverter {
|
||||||
|
my $paref = shift;
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $arg = $paref->{arg};
|
||||||
|
my $hash = $defs{$name};
|
||||||
|
|
||||||
|
my $ret = listDataPool ($hash, 'inverters', $arg);
|
||||||
|
$ret .= lineFromSpaces ($ret, 30);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################
|
###############################################################
|
||||||
# Getter solApiData
|
# Getter solApiData
|
||||||
###############################################################
|
###############################################################
|
||||||
@ -5708,6 +5766,7 @@ sub _attrInverterDev { ## no critic "not used"
|
|||||||
return if(!$init_done);
|
return if(!$init_done);
|
||||||
|
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
|
my $in = (split 'setupInverterDev', $aName)[1];
|
||||||
|
|
||||||
if ($paref->{cmd} eq 'set') {
|
if ($paref->{cmd} eq 'set') {
|
||||||
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
|
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => $aVal, method => 'string' } );
|
||||||
@ -5725,13 +5784,16 @@ sub _attrInverterDev { ## no critic "not used"
|
|||||||
}
|
}
|
||||||
elsif ($paref->{cmd} eq 'del') {
|
elsif ($paref->{cmd} eq 'del') {
|
||||||
readingsDelete ($hash, "Current_PV");
|
readingsDelete ($hash, "Current_PV");
|
||||||
deleteReadingspec ($hash, ".*_PVreal" );
|
|
||||||
undef @{$data{$type}{$name}{current}{genslidereg}};
|
undef @{$data{$type}{$name}{current}{genslidereg}};
|
||||||
|
|
||||||
|
if ($in eq '01') { # wenn der letzte Inverter gelöscht wurde
|
||||||
|
deleteReadingspec ($hash, ".*_PVreal" );
|
||||||
delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
|
delete $data{$type}{$name}{circular}{99}{attrInvChangedTs};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete $data{$type}{$name}{current}{invertercapi01};
|
delete $data{$type}{$name}{inverters}{$in}{invertercap};
|
||||||
delete $data{$type}{$name}{current}{iconi01};
|
delete $data{$type}{$name}{inverters}{$in}{iicon};
|
||||||
|
|
||||||
InternalTimer (gettimeofday()+0.5, 'FHEM::SolarForecast::centralTask', [$name, 0], 0);
|
InternalTimer (gettimeofday()+0.5, 'FHEM::SolarForecast::centralTask', [$name, 0], 0);
|
||||||
InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
|
InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
|
||||||
@ -8175,7 +8237,7 @@ sub __calcPVestimates {
|
|||||||
|
|
||||||
$pvsum = $peaksum if($peaksum && $pvsum > $peaksum); # Vorhersage nicht größer als die Summe aller PV-Strings Peak
|
$pvsum = $peaksum if($peaksum && $pvsum > $peaksum); # Vorhersage nicht größer als die Summe aller PV-Strings Peak
|
||||||
|
|
||||||
my $invcap = CurrentVal ($hash, 'invertercapi01', 0); # Max. Leistung des Invertrs
|
my $invcap = InverterVal ($hash, '01', 'invertercap', 0); # Max. Leistung des Invertrs
|
||||||
|
|
||||||
if ($invcap && $pvsum > $invcap) {
|
if ($invcap && $pvsum > $invcap) {
|
||||||
$pvsum = $invcap; # PV Vorhersage auf WR Kapazität begrenzen
|
$pvsum = $invcap; # PV Vorhersage auf WR Kapazität begrenzen
|
||||||
@ -8373,64 +8435,60 @@ return;
|
|||||||
sub _transferInverterValues {
|
sub _transferInverterValues {
|
||||||
my $paref = shift;
|
my $paref = shift;
|
||||||
my $name = $paref->{name};
|
my $name = $paref->{name};
|
||||||
|
my $type = $paref->{type};
|
||||||
my $t = $paref->{t}; # aktuelle Unix-Zeit
|
my $t = $paref->{t}; # aktuelle Unix-Zeit
|
||||||
my $chour = $paref->{chour};
|
my $chour = $paref->{chour};
|
||||||
my $day = $paref->{day};
|
my $day = $paref->{day};
|
||||||
|
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'setupInverterDev', method => 'attr' } );
|
my ($acu, $aln) = isAutoCorrUsed ($name);
|
||||||
return if($err);
|
my $nhour = $chour + 1;
|
||||||
|
my $warn = '';
|
||||||
|
my $pvsum = 0; # Summe aktuelle PV aller Inverter
|
||||||
|
my $ethishoursum = 0; # Summe Erzeugung akt. Stunde aller Inverter
|
||||||
|
|
||||||
my $type = $paref->{type};
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
|
||||||
|
my ($err, $indev, $h) = isDeviceValid ( { name => $name, obj => 'setupInverterDev'.$in, method => 'attr' } );
|
||||||
|
next if($err);
|
||||||
|
|
||||||
my ($pvread,$pvunit) = split ":", $h->{pv}; # Readingname/Unit für aktuelle PV Erzeugung
|
my ($pvread,$pvunit) = split ":", $h->{pv}; # Readingname/Unit für aktuelle PV Erzeugung
|
||||||
my ($edread,$etunit) = split ":", $h->{etotal}; # Readingname/Unit für Energie total (PV Erzeugung)
|
my ($edread,$etunit) = split ":", $h->{etotal}; # Readingname/Unit für Energie total (PV Erzeugung)
|
||||||
|
|
||||||
return if(!$pvread || !$edread);
|
next if(!$pvread || !$edread);
|
||||||
|
|
||||||
my $pvuf = $pvunit =~ /^kW$/xi ? 1000 : 1;
|
my $pvuf = $pvunit =~ /^kW$/xi ? 1000 : 1;
|
||||||
my $pv = ReadingsNum ($indev, $pvread, 0) * $pvuf; # aktuelle Erzeugung (W)
|
my $pv = ReadingsNum ($indev, $pvread, 0) * $pvuf; # aktuelle Erzeugung (W)
|
||||||
$pv = $pv < 0 ? 0 : sprintf("%.0f", $pv); # Forum: https://forum.fhem.de/index.php/topic,117864.msg1159718.html#msg1159718, https://forum.fhem.de/index.php/topic,117864.msg1166201.html#msg1166201
|
$pv = $pv < 0 ? 0 : sprintf("%.0f", $pv); # Forum: https://forum.fhem.de/index.php/topic,117864.msg1159718.html#msg1159718, https://forum.fhem.de/index.php/topic,117864.msg1166201.html#msg1166201
|
||||||
|
|
||||||
push @{$data{$type}{$name}{current}{genslidereg}}, $pv; # Schieberegister PV Erzeugung
|
|
||||||
limitArray ($data{$type}{$name}{current}{genslidereg}, $slidenumdef);
|
|
||||||
|
|
||||||
my $etuf = $etunit =~ /^kWh$/xi ? 1000 : 1;
|
my $etuf = $etunit =~ /^kWh$/xi ? 1000 : 1;
|
||||||
my $etotal = ReadingsNum ($indev, $edread, 0) * $etuf; # Erzeugung total (Wh)
|
my $etotal = ReadingsNum ($indev, $edread, 0) * $etuf; # Erzeugung total (Wh)
|
||||||
|
|
||||||
debugLog ($paref, "collectData", "collect Inverter data - device: $indev =>");
|
my $histetot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), 'etotali'.$in, 0); # etotal zu Beginn einer Stunde
|
||||||
debugLog ($paref, "collectData", "pv: $pv W, etotal: $etotal Wh");
|
|
||||||
|
|
||||||
my $nhour = $chour + 1;
|
|
||||||
my $histetot = HistoryVal ($hash, $day, sprintf("%02d",$nhour), 'etotal', 0); # etotal zu Beginn einer Stunde
|
|
||||||
my $warn = '';
|
|
||||||
my ($ethishour, $etotsvd);
|
my ($ethishour, $etotsvd);
|
||||||
|
|
||||||
if (!$histetot) { # etotal der aktuelle Stunde gesetzt ?
|
if (!$histetot) { # etotal der aktuelle Stunde gesetzt ?
|
||||||
writeToHistory ( { paref => $paref, key => 'etotal', val => $etotal, hour => $nhour } );
|
writeToHistory ( { paref => $paref, key => 'etotali'.$in, val => $etotal, hour => $nhour } );
|
||||||
|
|
||||||
$etotsvd = CurrentVal ($hash, 'etotali01', $etotal);
|
$etotsvd = InverterVal ($hash, $in, 'ietotal', $etotal);
|
||||||
$ethishour = int ($etotal - $etotsvd);
|
$ethishour = int ($etotal - $etotsvd);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ethishour = int ($etotal - $histetot);
|
$ethishour = int ($etotal - $histetot);
|
||||||
if (defined $h->{capacity} && $ethishour > 2 x $h->{capacity}) { # Schutz vor plötzlichem Anstieg von 0 auf mehr als doppelte WR-Kapazität
|
|
||||||
|
if (defined $h->{capacity} && $ethishour > 2 * $h->{capacity}) { # Schutz vor plötzlichem Anstieg von 0 auf mehr als doppelte WR-Kapazität
|
||||||
Log3 ($name, 1, "$name - WARNING - The generated PV of Inverter '$indev' is much more higher than inverter capacity. It seems to be a failure and Energy Total is reinitialized.");
|
Log3 ($name, 1, "$name - WARNING - The generated PV of Inverter '$indev' is much more higher than inverter capacity. It seems to be a failure and Energy Total is reinitialized.");
|
||||||
$warn = ' (WARNING: too much generated PV was registered - see log file)';
|
$warn = ' (WARNING: too much generated PV was registered - see log file)';
|
||||||
|
|
||||||
writeToHistory ( { paref => $paref, key => 'etotal', val => $etotal, hour => $nhour } );
|
writeToHistory ( { paref => $paref, key => 'etotali'.$in, val => $etotal, hour => $nhour } );
|
||||||
|
|
||||||
$etotsvd = CurrentVal ($hash, 'etotali01', $etotal);
|
$etotsvd = InverterVal ($hash, $in, 'ietotal', $etotal);
|
||||||
$ethishour = int ($etotal - $etotsvd);
|
$ethishour = int ($etotal - $etotsvd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$data{$type}{$name}{current}{generationi01} = $pv; # Hilfshash Wert current generation, Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
|
||||||
$data{$type}{$name}{current}{etotali01} = $etotal; # aktuellen etotal des WR speichern
|
|
||||||
$data{$type}{$name}{current}{namei01} = $indev; # Name des Inverterdevices
|
|
||||||
$data{$type}{$name}{current}{invertercapi01} = $h->{capacity} if(defined $h->{capacity}); # optionale Angabe max. WR-Leistung
|
|
||||||
$data{$type}{$name}{current}{iconi01} = $h->{icon} if($h->{icon}); # Icon des Inverters
|
|
||||||
|
|
||||||
if ($ethishour < 0) {
|
if ($ethishour < 0) {
|
||||||
$ethishour = 0;
|
$ethishour = 0;
|
||||||
my $vl = 3;
|
my $vl = 3;
|
||||||
@ -8441,18 +8499,42 @@ sub _transferInverterValues {
|
|||||||
$pre = 'DEBUG> - WARNING -';
|
$pre = 'DEBUG> - WARNING -';
|
||||||
}
|
}
|
||||||
|
|
||||||
Log3 ($name, $vl, "$name $pre The Total Energy of Inverter '$indev' is lower than the value saved before. This situation is unexpected and the Energy generated of current hour is set to '0'.");
|
Log3 ($name, $vl, "$name $pre The Total Energy of Inverter '$indev' is lower than the value saved before. This situation is unexpected and the Energy generated of current hour of this inverter is set to '0'.");
|
||||||
$warn = ' (WARNING invalid real PV occured - see Logfile)';
|
$warn = ' (WARNING invalid real PV occured - see Logfile)';
|
||||||
}
|
}
|
||||||
|
|
||||||
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_PVreal', $ethishour.' Wh'.$warn);
|
#$data{$type}{$name}{current}{generationi01} = $pv; # Hilfshash Wert current generation, Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
||||||
storeReading ('Current_PV', $pv.' W');
|
#$data{$type}{$name}{current}{etotali01} = $etotal; # aktuellen etotal des WR speichern
|
||||||
|
#$data{$type}{$name}{current}{namei01} = $indev; # Name des Inverterdevices
|
||||||
|
#$data{$type}{$name}{current}{invertercapi01} = $h->{capacity} if(defined $h->{capacity}); # optionale Angabe max. WR-Leistung
|
||||||
|
#$data{$type}{$name}{current}{iconi01} = $h->{icon} if($h->{icon}); # Icon des Inverters
|
||||||
|
|
||||||
$data{$type}{$name}{circular}{sprintf("%02d",$nhour)}{pvrl} = $ethishour; # Ringspeicher PV real Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
$data{$type}{$name}{inverters}{$in}{igeneration} = $pv; # Hilfshash Wert current generation, Forum: https://forum.fhem.de/index.php/topic,117864.msg1139251.html#msg1139251
|
||||||
|
$data{$type}{$name}{inverters}{$in}{ietotal} = $etotal; # aktuellen etotal des WR speichern
|
||||||
|
$data{$type}{$name}{inverters}{$in}{iname} = $indev; # Name des Inverterdevices
|
||||||
|
$data{$type}{$name}{inverters}{$in}{invertercap} = $h->{capacity} if(defined $h->{capacity}); # optionale Angabe max. WR-Leistung
|
||||||
|
$data{$type}{$name}{inverters}{$in}{iicon} = $h->{icon} if($h->{icon}); # Icon des Inverters
|
||||||
|
|
||||||
my ($acu, $aln) = isAutoCorrUsed ($name);
|
$pvsum += $pv;
|
||||||
|
$ethishoursum += $ethishour;
|
||||||
|
|
||||||
writeToHistory ( { paref => $paref, key => 'pvrl', val => $ethishour, hour => $nhour, valid => $aln } ); # valid=1: beim Learning berücksichtigen, 0: nicht
|
writeToHistory ( { paref => $paref, key => 'pvrl'.$in, val => $ethishour, hour => $nhour } );
|
||||||
|
|
||||||
|
debugLog ($paref, "collectData", "collect Inverter $in data - device: $indev =>");
|
||||||
|
debugLog ($paref, "collectData", "pv: $pv W, etotal: $etotal Wh");
|
||||||
|
}
|
||||||
|
|
||||||
|
storeReading ('Current_PV', $pvsum.' W');
|
||||||
|
storeReading ('Today_Hour'.sprintf("%02d",$nhour).'_PVreal', $ethishoursum.' Wh'.$warn);
|
||||||
|
|
||||||
|
$data{$type}{$name}{circular}{sprintf("%02d",$nhour)}{pvrl} = $ethishoursum; # Ringspeicher PV real Forum: https://forum.fhem.de/index.php/topic,117864.msg1133350.html#msg1133350
|
||||||
|
|
||||||
|
push @{$data{$type}{$name}{current}{genslidereg}}, $pvsum; # Schieberegister PV Erzeugung
|
||||||
|
limitArray ($data{$type}{$name}{current}{genslidereg}, $slidenumdef);
|
||||||
|
|
||||||
|
writeToHistory ( { paref => $paref, key => 'pvrl', val => $ethishoursum, hour => $nhour, valid => $aln } ); # valid=1: beim Learning berücksichtigen, 0: nicht
|
||||||
|
|
||||||
|
debugLog ($paref, "collectData", "summary data of all Inverters - pv: $pvsum W, this hour Generation: $ethishoursum Wh");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -8491,7 +8573,7 @@ sub _transferProducerValues {
|
|||||||
my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1;
|
my $etu = $etunit =~ /^kWh$/xi ? 1000 : 1;
|
||||||
my $etotal = ReadingsNum ($prdev, $edread, 0) * $etu; # Erzeugung total (Wh)
|
my $etotal = ReadingsNum ($prdev, $edread, 0) * $etu; # Erzeugung total (Wh)
|
||||||
|
|
||||||
debugLog ($paref, "collectData", "collect Producer$prn data - device: $prdev =>");
|
debugLog ($paref, "collectData", "collect Producer $prn data - device: $prdev =>");
|
||||||
debugLog ($paref, "collectData", "pcurr: $p W, etotalp$prn: $etotal Wh");
|
debugLog ($paref, "collectData", "pcurr: $p W, etotalp$prn: $etotal Wh");
|
||||||
|
|
||||||
my $nhour = $chour + 1;
|
my $nhour = $chour + 1;
|
||||||
@ -9185,11 +9267,17 @@ sub _createSummaries {
|
|||||||
|
|
||||||
my $gcon = CurrentVal ($hash, 'gridconsumption', 0); # aktueller Netzbezug
|
my $gcon = CurrentVal ($hash, 'gridconsumption', 0); # aktueller Netzbezug
|
||||||
my $tconsum = CurrentVal ($hash, 'tomorrowconsumption', undef); # Verbrauchsprognose für folgenden Tag
|
my $tconsum = CurrentVal ($hash, 'tomorrowconsumption', undef); # Verbrauchsprognose für folgenden Tag
|
||||||
my $pvgen = CurrentVal ($hash, 'generationi01', 0);
|
|
||||||
my $gfeedin = CurrentVal ($hash, 'gridfeedin', 0);
|
my $gfeedin = CurrentVal ($hash, 'gridfeedin', 0);
|
||||||
my $batin = CurrentVal ($hash, 'powerbatin', 0); # aktuelle Batterieladung
|
my $batin = CurrentVal ($hash, 'powerbatin', 0); # aktuelle Batterieladung
|
||||||
my $batout = CurrentVal ($hash, 'powerbatout', 0); # aktuelle Batterieentladung
|
my $batout = CurrentVal ($hash, 'powerbatout', 0); # aktuelle Batterieentladung
|
||||||
|
|
||||||
|
my $pvgen = 0;
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) { # Summe alle Inverter
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
$pvgen += InverterVal ($hash, $in, 'igeneration', 0);
|
||||||
|
}
|
||||||
|
|
||||||
my $othprod = 0; # Summe Otherproducer
|
my $othprod = 0; # Summe Otherproducer
|
||||||
|
|
||||||
for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
|
for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
|
||||||
@ -11171,7 +11259,7 @@ sub calcValueImproves {
|
|||||||
my $t = $paref->{t}; # aktuelle Unix-Zeit
|
my $t = $paref->{t}; # aktuelle Unix-Zeit
|
||||||
|
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my $idts = CircularVal ($hash, 99, "attrInvChangedTs", ''); # Definitionstimestamp des Attr setupInverterDev
|
my $idts = CircularVal ($hash, 99, "attrInvChangedTs", ''); # Definitionstimestamp des Attr setupInverterDev01
|
||||||
|
|
||||||
return if(!$idts);
|
return if(!$idts);
|
||||||
|
|
||||||
@ -12080,7 +12168,7 @@ sub _checkSetupNotComplete {
|
|||||||
my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig
|
my $is = AttrVal ($name, 'setupInverterStrings', undef); # String Konfig
|
||||||
my $wedev = AttrVal ($name, 'setupWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.)
|
my $wedev = AttrVal ($name, 'setupWeatherDev1', undef); # Device Vorhersage Wetterdaten (Bewölkung etc.)
|
||||||
my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
|
my $radev = AttrVal ($name, 'setupRadiationAPI', undef); # Device Strahlungsdaten Vorhersage
|
||||||
my $indev = AttrVal ($name, 'setupInverterDev', undef); # Inverter Device
|
my $indev = AttrVal ($name, 'setupInverterDev01', undef); # Inverter Device
|
||||||
my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
|
my $medev = AttrVal ($name, 'setupMeterDev', undef); # Meter Device
|
||||||
my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak
|
my $peaks = AttrVal ($name, 'setupStringPeak', undef); # String Peak
|
||||||
my $maz = ReadingsVal ($name, 'setupStringAzimuth', undef); # Modulausrichtung Konfig (Azimut)
|
my $maz = ReadingsVal ($name, 'setupStringAzimuth', undef); # Modulausrichtung Konfig (Azimut)
|
||||||
@ -13974,7 +14062,6 @@ sub _flowGraphic {
|
|||||||
my $cgfi = ReadingsNum ($name, 'Current_GridFeedIn', 0);
|
my $cgfi = ReadingsNum ($name, 'Current_GridFeedIn', 0);
|
||||||
my $csc = ReadingsNum ($name, 'Current_SelfConsumption', 0);
|
my $csc = ReadingsNum ($name, 'Current_SelfConsumption', 0);
|
||||||
my $cc = CurrentVal ($hash, 'consumption', 0);
|
my $cc = CurrentVal ($hash, 'consumption', 0);
|
||||||
my $cpv = CurrentVal ($hash, 'generationi01', 0);
|
|
||||||
my $batin = ReadingsNum ($name, 'Current_PowerBatIn', undef);
|
my $batin = ReadingsNum ($name, 'Current_PowerBatIn', undef);
|
||||||
my $batout = ReadingsNum ($name, 'Current_PowerBatOut', undef);
|
my $batout = ReadingsNum ($name, 'Current_PowerBatOut', undef);
|
||||||
my $soc = ReadingsNum ($name, 'Current_BatCharge', 100);
|
my $soc = ReadingsNum ($name, 'Current_BatCharge', 100);
|
||||||
@ -13986,6 +14073,25 @@ sub _flowGraphic {
|
|||||||
my $ppcurr = {}; # Hashref Producer current power
|
my $ppcurr = {}; # Hashref Producer current power
|
||||||
my $cpcurr = {}; # Hashref Consumer current power
|
my $cpcurr = {}; # Hashref Consumer current power
|
||||||
|
|
||||||
|
## definierte Inverter ermitteln und deren
|
||||||
|
## aktuelle Leistung bestimmen
|
||||||
|
############################################
|
||||||
|
my $invertercount = 0;
|
||||||
|
my $pvall = 0; # Summe Erzeugung alle Inverter
|
||||||
|
my @inverters;
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) {
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
my $p = InverterVal ($hash, $in, 'igeneration', 0);
|
||||||
|
|
||||||
|
if (defined $p) {
|
||||||
|
push @inverters, $in;
|
||||||
|
$ppcurr->{$in} = $p;
|
||||||
|
$invertercount += 1;
|
||||||
|
$pvall += $p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
## definierte Producer ermitteln und deren
|
## definierte Producer ermitteln und deren
|
||||||
## aktuelle Leistung bestimmen
|
## aktuelle Leistung bestimmen
|
||||||
############################################
|
############################################
|
||||||
@ -13993,12 +14099,12 @@ sub _flowGraphic {
|
|||||||
my $ppall = 0; # Summe Erzeugung alle Poducer
|
my $ppall = 0; # Summe Erzeugung alle Poducer
|
||||||
my @producers;
|
my @producers;
|
||||||
|
|
||||||
for my $i (1..$maxproducer) {
|
for my $pn (1..$maxproducer) {
|
||||||
my $pn = sprintf "%02d", $i;
|
$pn = sprintf "%02d", $pn;
|
||||||
my $p = CurrentVal ($hash, 'generationp'.$pn, undef);
|
my $p = CurrentVal ($hash, 'generationp'.$pn, undef);
|
||||||
|
|
||||||
if (defined $p) {
|
if (defined $p) {
|
||||||
push @producers, sprintf "%02d", $i;
|
push @producers, $pn;
|
||||||
$ppcurr->{$pn} = $p;
|
$ppcurr->{$pn} = $p;
|
||||||
$producercount += 1;
|
$producercount += 1;
|
||||||
$ppall += $p;
|
$ppall += $p;
|
||||||
@ -14037,7 +14143,7 @@ sub _flowGraphic {
|
|||||||
my $cgc_direction = 'M490,515 L670,590'; # Batterientladung ins Netz
|
my $cgc_direction = 'M490,515 L670,590'; # Batterientladung ins Netz
|
||||||
|
|
||||||
if ($batout) { # Batterie wird entladen
|
if ($batout) { # Batterie wird entladen
|
||||||
my $cgfo = $cgfi - $cpv;
|
my $cgfo = $cgfi - $pvall;
|
||||||
|
|
||||||
if ($cgfo > 1) {
|
if ($cgfo > 1) {
|
||||||
$cgc_style = 'flowg active_out';
|
$cgc_style = 'flowg active_out';
|
||||||
@ -14050,7 +14156,7 @@ sub _flowGraphic {
|
|||||||
my $batout_direction = 'M902,515 L730,590';
|
my $batout_direction = 'M902,515 L730,590';
|
||||||
|
|
||||||
if ($batin) { # Batterie wird geladen
|
if ($batin) { # Batterie wird geladen
|
||||||
my $gbi = $batin - $cpv;
|
my $gbi = $batin - $pvall;
|
||||||
|
|
||||||
if ($gbi > 1) { # Batterieladung anteilig aus Hausnetz geladen
|
if ($gbi > 1) { # Batterieladung anteilig aus Hausnetz geladen
|
||||||
$batin -= $gbi;
|
$batin -= $gbi;
|
||||||
@ -14063,7 +14169,7 @@ sub _flowGraphic {
|
|||||||
## Werte / SteuerungVars anpassen
|
## Werte / SteuerungVars anpassen
|
||||||
###################################
|
###################################
|
||||||
$flowgcons = 0 if(!$consumercount); # Consumer Anzeige ausschalten wenn keine Consumer definiert
|
$flowgcons = 0 if(!$consumercount); # Consumer Anzeige ausschalten wenn keine Consumer definiert
|
||||||
$flowgprods = 0 if(!$producercount); # Producer Anzeige ausschalten wenn keine Producer definiert
|
$flowgprods = 0 if(!$producercount && !$invertercount); # Producer Anzeige ausschalten wenn keine Producer / Inverter definiert
|
||||||
my $p2home = sprintf "%.1f", ($csc + $ppall); # Energiefluß von Sonne zum Haus: Selbstverbrauch + alle Producer
|
my $p2home = sprintf "%.1f", ($csc + $ppall); # Energiefluß von Sonne zum Haus: Selbstverbrauch + alle Producer
|
||||||
$p2home = sprintf "%.0f", $p2home if($p2home > 10);
|
$p2home = sprintf "%.0f", $p2home if($p2home > 10);
|
||||||
$p2home = 0 if($p2home == 0); # 0.0 eliminieren wenn keine Leistung zum Haus
|
$p2home = 0 if($p2home == 0); # 0.0 eliminieren wenn keine Leistung zum Haus
|
||||||
@ -14111,12 +14217,12 @@ END0
|
|||||||
|
|
||||||
$pos_left = $producer_start + 25;
|
$pos_left = $producer_start + 25;
|
||||||
|
|
||||||
for my $prnxnum (@producers) {
|
for my $prn (@producers) {
|
||||||
my $palias = CurrentVal ($hash, 'aliasp'.$prnxnum, 'namep'.$prnxnum);
|
my $palias = CurrentVal ($hash, 'aliasp'.$prn, 'namep'.$prn);
|
||||||
my ($picon) = __substituteIcon ( { hash => $hash, # Icon des Producerdevices
|
my ($picon) = __substituteIcon ( { hash => $hash, # Icon des Producerdevices
|
||||||
name => $name,
|
name => $name,
|
||||||
pn => $prnxnum,
|
pn => $prn,
|
||||||
pcurr => $ppcurr->{$prnxnum},
|
pcurr => $ppcurr->{$prn},
|
||||||
lang => $lang
|
lang => $lang
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -14124,7 +14230,7 @@ END0
|
|||||||
$picon = FW_makeImage ($picon, '');
|
$picon = FW_makeImage ($picon, '');
|
||||||
($scale, $picon) = __normIconScale ($picon, $name);
|
($scale, $picon) = __normIconScale ($picon, $name);
|
||||||
|
|
||||||
$ret .= qq{<g id="producer_$prnxnum" fill="grey" transform="translate($pos_left,0),scale($scale)">};
|
$ret .= qq{<g id="producer_$prn" fill="grey" transform="translate($pos_left,0),scale($scale)">};
|
||||||
$ret .= "<title>$palias</title>".$picon;
|
$ret .= "<title>$palias</title>".$picon;
|
||||||
$ret .= '</g> ';
|
$ret .= '</g> ';
|
||||||
|
|
||||||
@ -14132,6 +14238,24 @@ END0
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## Inverter Icon
|
||||||
|
######################
|
||||||
|
my ($iicon, $smtxt) = __substituteIcon ( { hash => $hash,
|
||||||
|
name => $name,
|
||||||
|
in => '01',
|
||||||
|
don => NexthoursVal ($hash, 'NextHour00', 'DoN', 0), # Tag oder Nacht
|
||||||
|
pcurr => $pvall,
|
||||||
|
lang => $lang
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$iicon = FW_makeImage ($iicon, '');
|
||||||
|
($scale, $iicon) = __normIconScale ($iicon, $name);
|
||||||
|
|
||||||
|
$ret .= qq{<g id="Inverter" transform="translate(360,165),scale($scale)">}; # translate(X-Koordinate,Y-Koordinate), scale(<Größe>)-> Koordinaten ändern sich bei Größenänderung
|
||||||
|
$ret .= "<title>$smtxt</title>".$iicon;
|
||||||
|
$ret .= '</g> ';
|
||||||
|
|
||||||
## Consumer Liste und Icons in Grafik anzeigen
|
## Consumer Liste und Icons in Grafik anzeigen
|
||||||
###############################################
|
###############################################
|
||||||
$pos_left = 0;
|
$pos_left = 0;
|
||||||
@ -14171,24 +14295,6 @@ END0
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Inverter Icon
|
|
||||||
######################
|
|
||||||
my ($iicon, $smtxt) = __substituteIcon ( { hash => $hash,
|
|
||||||
name => $name,
|
|
||||||
in => '01',
|
|
||||||
don => NexthoursVal ($hash, 'NextHour00', 'DoN', 0), # Tag oder Nacht
|
|
||||||
pcurr => $cpv,
|
|
||||||
lang => $lang
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
$iicon = FW_makeImage ($iicon, '');
|
|
||||||
($scale, $iicon) = __normIconScale ($iicon, $name);
|
|
||||||
|
|
||||||
$ret .= qq{<g id="Inverter" transform="translate(360,165),scale($scale)">}; # translate(X-Koordinate,Y-Koordinate), scale(<Größe>)-> Koordinaten ändern sich bei Größenänderung
|
|
||||||
$ret .= "<title>$smtxt</title>".$iicon;
|
|
||||||
$ret .= '</g> ';
|
|
||||||
|
|
||||||
## Batterie Icon
|
## Batterie Icon
|
||||||
##################
|
##################
|
||||||
if ($hasbat) {
|
if ($hasbat) {
|
||||||
@ -14277,8 +14383,8 @@ END3
|
|||||||
$pos_left_start_con = 700 - ((($distance_con ) / 2) * ($producercount-1));
|
$pos_left_start_con = 700 - ((($distance_con ) / 2) * ($producercount-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
for my $prnxnum (@producers) {
|
for my $prn (@producers) {
|
||||||
my $p = $ppcurr->{$prnxnum};
|
my $p = $ppcurr->{$prn};
|
||||||
my $consumer_style = 'flowg inactive_out';
|
my $consumer_style = 'flowg inactive_out';
|
||||||
$consumer_style = 'flowg active_out' if($p > 0);
|
$consumer_style = 'flowg active_out' if($p > 0);
|
||||||
my $chain_color = ''; # Farbe der Laufkette des Producers
|
my $chain_color = ''; # Farbe der Laufkette des Producers
|
||||||
@ -14288,7 +14394,7 @@ END3
|
|||||||
$chain_color = 'style="stroke: darkorange;"';
|
$chain_color = 'style="stroke: darkorange;"';
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret .= qq{<path id="genproducer_$prnxnum " class="$consumer_style" $chain_color d=" M$pos_left,130 L$pos_left_start_con,200" />}; # Design Consumer Laufkette
|
$ret .= qq{<path id="genproducer_$prn " class="$consumer_style" $chain_color d=" M$pos_left,130 L$pos_left_start_con,200" />}; # Design Consumer Laufkette
|
||||||
$pos_left += ($consDist * 2);
|
$pos_left += ($consDist * 2);
|
||||||
$pos_left_start_con += $distance_con;
|
$pos_left_start_con += $distance_con;
|
||||||
}
|
}
|
||||||
@ -14337,7 +14443,7 @@ END3
|
|||||||
## Textangaben an Grafikelementen
|
## Textangaben an Grafikelementen
|
||||||
###################################
|
###################################
|
||||||
$cc_dummy = sprintf("%.0f", $cc_dummy); # Verbrauch Dummy-Consumer
|
$cc_dummy = sprintf("%.0f", $cc_dummy); # Verbrauch Dummy-Consumer
|
||||||
$ret .= qq{<text class="flowg text" id="pv-txt" x="800" y="320" style="text-anchor: start;">$cpv</text>} if ($cpv);
|
$ret .= qq{<text class="flowg text" id="pv-txt" x="800" y="320" style="text-anchor: start;">$pvall</text>} if ($pvall);
|
||||||
$ret .= qq{<text class="flowg text" id="bat-txt" x="1110" y="520" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Text Batterieladungszustand
|
$ret .= qq{<text class="flowg text" id="bat-txt" x="1110" y="520" style="text-anchor: start;">$soc %</text>} if ($hasbat); # Lage Text Batterieladungszustand
|
||||||
$ret .= qq{<text class="flowg text" id="pv_home-txt" x="730" y="520" style="text-anchor: start;">$p2home</text>} if ($p2home);
|
$ret .= qq{<text class="flowg text" id="pv_home-txt" x="730" y="520" style="text-anchor: start;">$p2home</text>} if ($p2home);
|
||||||
$ret .= qq{<text class="flowg text" id="pv-grid-txt" x="525" y="420" style="text-anchor: end;">$cgfi</text>} if ($cgfi);
|
$ret .= qq{<text class="flowg text" id="pv-grid-txt" x="525" y="420" style="text-anchor: end;">$cgfi</text>} if ($cgfi);
|
||||||
@ -14354,8 +14460,8 @@ END3
|
|||||||
if ($flowgprods) {
|
if ($flowgprods) {
|
||||||
$pos_left = ($producer_start * 2) - 50; # -XX -> Start Lage producer Beschriftung
|
$pos_left = ($producer_start * 2) - 50; # -XX -> Start Lage producer Beschriftung
|
||||||
|
|
||||||
for my $prnxnum (@producers) {
|
for my $prn (@producers) {
|
||||||
$currentPower = sprintf "%.2f", $ppcurr->{$prnxnum};
|
$currentPower = sprintf "%.2f", $ppcurr->{$prn};
|
||||||
$currentPower = sprintf "%.0f", $currentPower if($currentPower > 10);
|
$currentPower = sprintf "%.0f", $currentPower if($currentPower > 10);
|
||||||
$currentPower = 0 if(1 * $currentPower == 0);
|
$currentPower = 0 if(1 * $currentPower == 0);
|
||||||
$lcp = length $currentPower;
|
$lcp = length $currentPower;
|
||||||
@ -14368,7 +14474,7 @@ END3
|
|||||||
elsif ($lcp == 2) {$pos_left += 20}
|
elsif ($lcp == 2) {$pos_left += 20}
|
||||||
elsif ($lcp == 1) {$pos_left += 40}
|
elsif ($lcp == 1) {$pos_left += 40}
|
||||||
|
|
||||||
$ret .= qq{<text class="flowg text" id="producer-txt_$prnxnum" x="$pos_left" y="80">$currentPower</text>} if($flowgconPower); # Lage producer Consumption
|
$ret .= qq{<text class="flowg text" id="producer-txt_$prn" x="$pos_left" y="80">$currentPower</text>} if($flowgconPower); # Lage producer Consumption
|
||||||
|
|
||||||
# Leistungszahl wieder zurück an den Ursprungspunkt
|
# Leistungszahl wieder zurück an den Ursprungspunkt
|
||||||
####################################################
|
####################################################
|
||||||
@ -14468,7 +14574,7 @@ sub __substituteIcon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ($in) { # Inverter, Smartloader
|
elsif ($in) { # Inverter, Smartloader
|
||||||
my ($iday, $inight) = split ':', CurrentVal ($hash, 'iconi'.$in, $invicondef);
|
my ($iday, $inight) = split ':', InverterVal ($hash, $in, 'iicon', $invicondef);
|
||||||
|
|
||||||
if ($don || $pcurr) { # Tag -> eigenes Icon oder Standard
|
if ($don || $pcurr) { # Tag -> eigenes Icon oder Standard
|
||||||
$iday = $iday ? $iday : $invicondef;
|
$iday = $iday ? $iday : $invicondef;
|
||||||
@ -15581,12 +15687,6 @@ sub listDataPool {
|
|||||||
my $don = HistoryVal ($hash, $day, $key, 'DoN', '-');
|
my $don = HistoryVal ($hash, $day, $key, 'DoN', '-');
|
||||||
my $conprc = HistoryVal ($hash, $day, $key, 'conprice', '-');
|
my $conprc = HistoryVal ($hash, $day, $key, 'conprice', '-');
|
||||||
my $feedprc = HistoryVal ($hash, $day, $key, 'feedprice', '-');
|
my $feedprc = HistoryVal ($hash, $day, $key, 'feedprice', '-');
|
||||||
my $etotp01 = HistoryVal ($hash, $day, $key, 'etotalp01', '-');
|
|
||||||
my $etotp02 = HistoryVal ($hash, $day, $key, 'etotalp02', '-');
|
|
||||||
my $etotp03 = HistoryVal ($hash, $day, $key, 'etotalp03', '-');
|
|
||||||
my $pprl01 = HistoryVal ($hash, $day, $key, 'pprl01', '-');
|
|
||||||
my $pprl02 = HistoryVal ($hash, $day, $key, 'pprl02', '-');
|
|
||||||
my $pprl03 = HistoryVal ($hash, $day, $key, 'pprl03', '-');
|
|
||||||
|
|
||||||
if ($export eq 'csv') {
|
if ($export eq 'csv') {
|
||||||
$hexp->{$day}{$key}{PVreal} = $pvrl;
|
$hexp->{$day}{$key}{PVreal} = $pvrl;
|
||||||
@ -15603,7 +15703,6 @@ sub listDataPool {
|
|||||||
$hexp->{$day}{$key}{PVCorrectionFactor} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[0];
|
$hexp->{$day}{$key}{PVCorrectionFactor} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[0];
|
||||||
$hexp->{$day}{$key}{Quality} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[1];
|
$hexp->{$day}{$key}{Quality} = $pvcorrf eq '-' ? '' : (split "/", $pvcorrf)[1];
|
||||||
$hexp->{$day}{$key}{DayName} = $dayname // '';
|
$hexp->{$day}{$key}{DayName} = $dayname // '';
|
||||||
$hexp->{$day}{$key}{Etotal} = $etotal;
|
|
||||||
$hexp->{$day}{$key}{BatteryInTotal} = $btotin;
|
$hexp->{$day}{$key}{BatteryInTotal} = $btotin;
|
||||||
$hexp->{$day}{$key}{BatteryIn} = $batin;
|
$hexp->{$day}{$key}{BatteryIn} = $batin;
|
||||||
$hexp->{$day}{$key}{BatteryOutTotal} = $btotout;
|
$hexp->{$day}{$key}{BatteryOutTotal} = $btotout;
|
||||||
@ -15616,12 +15715,6 @@ sub listDataPool {
|
|||||||
$hexp->{$day}{$key}{DayOrNight} = $don;
|
$hexp->{$day}{$key}{DayOrNight} = $don;
|
||||||
$hexp->{$day}{$key}{PurchasePrice} = $conprc;
|
$hexp->{$day}{$key}{PurchasePrice} = $conprc;
|
||||||
$hexp->{$day}{$key}{FeedInPrice} = $feedprc;
|
$hexp->{$day}{$key}{FeedInPrice} = $feedprc;
|
||||||
$hexp->{$day}{$key}{etotalp01} = $etotp01;
|
|
||||||
$hexp->{$day}{$key}{etotalp02} = $etotp02;
|
|
||||||
$hexp->{$day}{$key}{etotalp03} = $etotp03;
|
|
||||||
$hexp->{$day}{$key}{pprl01} = $pprl01;
|
|
||||||
$hexp->{$day}{$key}{pprl02} = $pprl02;
|
|
||||||
$hexp->{$day}{$key}{pprl03} = $pprl03;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret .= "\n " if($ret);
|
$ret .= "\n " if($ret);
|
||||||
@ -15629,10 +15722,61 @@ sub listDataPool {
|
|||||||
$ret .= "etotal: $etotal, " if($key ne '99');
|
$ret .= "etotal: $etotal, " if($key ne '99');
|
||||||
$ret .= "pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h";
|
$ret .= "pvfc: $pvfc, pvrl: $pvrl, pvrlvd: $pvrlvd, rad1h: $rad1h";
|
||||||
$ret .= "\n ";
|
$ret .= "\n ";
|
||||||
$ret .= "etotalp01: $etotp01, etotalp02: $etotp02, etotalp03: $etotp03" if($key ne '99');
|
|
||||||
$ret .= "\n " if($key ne '99');
|
my ($inve, $invl);
|
||||||
$ret .= "pprl01: $pprl01, pprl02: $pprl02, pprl03: $pprl03";
|
for my $in (1..$maxinverter) { # + alle Inverter
|
||||||
$ret .= "\n ";
|
$in = sprintf "%02d", $in;
|
||||||
|
my $etoti = HistoryVal ($hash, $day, $key, 'etotali'.$in, '-');
|
||||||
|
my $pvrli = HistoryVal ($hash, $day, $key, 'pvrl'.$in, '-');
|
||||||
|
|
||||||
|
if ($export eq 'csv') {
|
||||||
|
$hexp->{$day}{$key}{"Etotal${in}"} = $etoti;
|
||||||
|
$hexp->{$day}{$key}{"PVreal${in}"} = $pvrli;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $etoti) {
|
||||||
|
$inve .= ', ' if($inve);
|
||||||
|
$inve .= "etotali${in}: $etoti";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $pvrli) {
|
||||||
|
$invl .= ', ' if($invl);
|
||||||
|
$invl .= "pvrl${in}: $pvrli";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret .= $inve if($inve && $key ne '99');
|
||||||
|
$ret .= "\n " if($inve && $key ne '99');
|
||||||
|
$ret .= $invl if($invl);
|
||||||
|
$ret .= "\n " if($invl);
|
||||||
|
|
||||||
|
my ($prde, $prdl);
|
||||||
|
for my $pn (1..$maxproducer) { # + alle Producer
|
||||||
|
$pn = sprintf "%02d", $pn;
|
||||||
|
my $etotp = HistoryVal ($hash, $day, $key, 'etotalp'.$pn, '-');
|
||||||
|
my $pprl = HistoryVal ($hash, $day, $key, 'pprl'.$pn, '-');
|
||||||
|
|
||||||
|
if ($export eq 'csv') {
|
||||||
|
$hexp->{$day}{$key}{"Etotal${pn}"} = $etotp;
|
||||||
|
$hexp->{$day}{$key}{"PPreal${pn}"} = $pprl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $etotp) {
|
||||||
|
$prde .= ', ' if($prde);
|
||||||
|
$prde .= "etotalp${pn}: $etotp";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $pprl) {
|
||||||
|
$prdl .= ', ' if($prdl);
|
||||||
|
$prdl .= "pprl${pn}: $pprl";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret .= $prde if($prde && $key ne '99');
|
||||||
|
$ret .= "\n " if($prde && $key ne '99');
|
||||||
|
$ret .= $prdl if($prdl);
|
||||||
|
$ret .= "\n " if($prdl);
|
||||||
|
|
||||||
$ret .= "confc: $confc, con: $con, gcons: $gcons, conprice: $conprc";
|
$ret .= "confc: $confc, con: $con, gcons: $gcons, conprice: $conprc";
|
||||||
$ret .= "\n ";
|
$ret .= "\n ";
|
||||||
$ret .= "gfeedin: $gfeedin, feedprice: $feedprc";
|
$ret .= "gfeedin: $gfeedin, feedprice: $feedprc";
|
||||||
@ -15656,7 +15800,7 @@ sub listDataPool {
|
|||||||
$ret .= "dayname: $dayname, " if($dayname);
|
$ret .= "dayname: $dayname, " if($dayname);
|
||||||
|
|
||||||
my $csm;
|
my $csm;
|
||||||
for my $c (1..$maxconsumer) {
|
for my $c (1..$maxconsumer) { # + alle Consumer
|
||||||
$c = sprintf "%02d", $c;
|
$c = sprintf "%02d", $c;
|
||||||
my $nl = 0;
|
my $nl = 0;
|
||||||
my $csmc = HistoryVal ($hash, $day, $key, "cyclescsm${c}", undef);
|
my $csmc = HistoryVal ($hash, $day, $key, "cyclescsm${c}", undef);
|
||||||
@ -15748,16 +15892,21 @@ sub listDataPool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($htol eq "consumer") {
|
if ($htol =~ /consumers|inverters/xs) {
|
||||||
$h = $data{$type}{$name}{consumers};
|
my $sub = $htol eq 'consumers' ? \&ConsumerVal :
|
||||||
|
$htol eq 'inverters' ? \&InverterVal :
|
||||||
|
'';
|
||||||
|
|
||||||
|
$h = $data{$type}{$name}{$htol};
|
||||||
|
|
||||||
if (!keys %{$h}) {
|
if (!keys %{$h}) {
|
||||||
return qq{Consumer cache is empty.};
|
return ucfirst($htol).qq{ cache is empty.};
|
||||||
}
|
}
|
||||||
|
|
||||||
for my $i (keys %{$h}) {
|
for my $i (keys %{$h}) {
|
||||||
if ($i !~ /^[0-9]{2}$/ix) { # bereinigen ungültige consumer, Forum: https://forum.fhem.de/index.php/topic,117864.msg1173219.html#msg1173219
|
if ($i !~ /^[0-9]{2}$/ix) { # bereinigen ungültige Position, Forum: https://forum.fhem.de/index.php/topic,117864.msg1173219.html#msg1173219
|
||||||
delete $data{$type}{$name}{consumers}{$i};
|
delete $data{$type}{$name}{$htol}{$i};
|
||||||
Log3 ($name, 2, qq{$name - INFO - invalid consumer key "$i" was deleted from consumer storage});
|
Log3 ($name, 2, qq{$name - INFO - invalid key "$i" was deleted from }.ucfirst($htol).qq{ storage});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15775,7 +15924,7 @@ sub listDataPool {
|
|||||||
$cret .= $ckey." => ".$hk."\n ";
|
$cret .= $ckey." => ".$hk."\n ";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$cret .= $ckey." => ".ConsumerVal ($hash, $idx, $ckey, "")."\n ";
|
$cret .= $ckey." => ". &{$sub} ($hash, $idx, $ckey, "")."\n ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17026,10 +17175,6 @@ sub createAssociatedWith {
|
|||||||
($ara,$h) = parseParams ($radev);
|
($ara,$h) = parseParams ($radev);
|
||||||
$radev = $ara->[0] // "";
|
$radev = $ara->[0] // "";
|
||||||
|
|
||||||
my $indev = AttrVal ($name, 'setupInverterDev', ''); # Inverter Device
|
|
||||||
($ain,$h) = parseParams ($indev);
|
|
||||||
$indev = $ain->[0] // "";
|
|
||||||
|
|
||||||
my $medev = AttrVal ($name, 'setupMeterDev', ''); # Meter Device
|
my $medev = AttrVal ($name, 'setupMeterDev', ''); # Meter Device
|
||||||
($ame,$h) = parseParams ($medev);
|
($ame,$h) = parseParams ($medev);
|
||||||
$medev = $ame->[0] // "";
|
$medev = $ame->[0] // "";
|
||||||
@ -17053,17 +17198,23 @@ sub createAssociatedWith {
|
|||||||
push @nd, $fcdev2 if($fcdev2 && $fcdev2 !~ /-API/xs);
|
push @nd, $fcdev2 if($fcdev2 && $fcdev2 !~ /-API/xs);
|
||||||
push @nd, $fcdev3 if($fcdev3 && $fcdev3 !~ /-API/xs);
|
push @nd, $fcdev3 if($fcdev3 && $fcdev3 !~ /-API/xs);
|
||||||
push @nd, $radev if($radev && $radev !~ /-API/xs);
|
push @nd, $radev if($radev && $radev !~ /-API/xs);
|
||||||
push @nd, $indev;
|
|
||||||
push @nd, $medev;
|
push @nd, $medev;
|
||||||
push @nd, $badev;
|
push @nd, $badev;
|
||||||
|
|
||||||
for my $prn (1..$maxproducer) {
|
for my $prn (1..$maxproducer) { # Producer Devices
|
||||||
$prn = sprintf "%02d", $prn;
|
$prn = sprintf "%02d", $prn;
|
||||||
my $pdc = AttrVal ($name, "setupOtherProducer${prn}", "");
|
my $pdc = AttrVal ($name, "setupOtherProducer${prn}", "");
|
||||||
my ($prd) = parseParams ($pdc);
|
my ($prd) = parseParams ($pdc);
|
||||||
push @nd, $prd->[0] if($prd->[0]);
|
push @nd, $prd->[0] if($prd->[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for my $in (1..$maxinverter) { # Inverter Devices
|
||||||
|
$in = sprintf "%02d", $in;
|
||||||
|
my $inc = AttrVal ($name, "setupInverterDev${in}", "");
|
||||||
|
my ($ind) = parseParams ($inc);
|
||||||
|
push @nd, $ind->[0] if($ind->[0]);
|
||||||
|
}
|
||||||
|
|
||||||
my @ndn = ();
|
my @ndn = ();
|
||||||
|
|
||||||
for my $e (@nd) {
|
for my $e (@nd) {
|
||||||
@ -18675,8 +18826,7 @@ return $def;
|
|||||||
# Usage:
|
# Usage:
|
||||||
# CurrentVal ($hash, $key, $def)
|
# CurrentVal ($hash, $key, $def)
|
||||||
#
|
#
|
||||||
# $key: generationiXX - aktuelle PV Erzeugung Inverter XX
|
# $key: generationpXX - aktuelle Erzeugung Producer XX
|
||||||
# generationpXX - aktuelle Erzeugung Producer XX
|
|
||||||
# aiinitstate - Initialisierungsstatus der KI
|
# aiinitstate - Initialisierungsstatus der KI
|
||||||
# aitrainstate - Traisningsstatus der KI
|
# aitrainstate - Traisningsstatus der KI
|
||||||
# aiaddistate - Add Instanz Status der KI
|
# aiaddistate - Add Instanz Status der KI
|
||||||
@ -18698,7 +18848,6 @@ return $def;
|
|||||||
# temp - aktuelle Außentemperatur
|
# temp - aktuelle Außentemperatur
|
||||||
# surplus - aktueller PV Überschuß
|
# surplus - aktueller PV Überschuß
|
||||||
# tomorrowconsumption - Verbrauch des kommenden Tages
|
# tomorrowconsumption - Verbrauch des kommenden Tages
|
||||||
# invertercapXX - Bemessungsleistung der Wechselrichters XX (max. W)
|
|
||||||
# allstringspeak - Peakleistung aller Strings nach temperaturabhängiger Korrektur
|
# allstringspeak - Peakleistung aller Strings nach temperaturabhängiger Korrektur
|
||||||
# allstringscount - aktuelle Anzahl der Anlagenstrings
|
# allstringscount - aktuelle Anzahl der Anlagenstrings
|
||||||
# tomorrowconsumption - erwarteter Gesamtverbrauch am morgigen Tag
|
# tomorrowconsumption - erwarteter Gesamtverbrauch am morgigen Tag
|
||||||
@ -18898,6 +19047,39 @@ sub ConsumerVal {
|
|||||||
return $def;
|
return $def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###################################################################################################
|
||||||
|
# Wert des Inverter-Hash zurückliefern
|
||||||
|
# Usage:
|
||||||
|
# InverterVal ($hash, $in, $key, $def)
|
||||||
|
#
|
||||||
|
# $in: Inverter Nummer (01,02,03,...)
|
||||||
|
# $key: etotal - Stand etotal des WR
|
||||||
|
# generation - aktuelle PV Erzeugung Inverter
|
||||||
|
# invertercap - Bemessungsleistung der Wechselrichters (max. W)
|
||||||
|
# name - Name des Inverterdevices
|
||||||
|
# icon - Icon des Inverters
|
||||||
|
#
|
||||||
|
# $def: Defaultwert
|
||||||
|
#
|
||||||
|
###################################################################################################
|
||||||
|
sub InverterVal {
|
||||||
|
my $hash = shift;
|
||||||
|
my $in = shift;
|
||||||
|
my $key = shift;
|
||||||
|
my $def = shift;
|
||||||
|
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $type = $hash->{TYPE};
|
||||||
|
|
||||||
|
if (defined($data{$type}{$name}{inverters}) &&
|
||||||
|
defined($data{$type}{$name}{inverters}{$in}{$key}) &&
|
||||||
|
defined($data{$type}{$name}{inverters}{$in}{$key})) {
|
||||||
|
return $data{$type}{$name}{inverters}{$in}{$key};
|
||||||
|
}
|
||||||
|
|
||||||
|
return $def;
|
||||||
|
}
|
||||||
|
|
||||||
##########################################################################################################################################################
|
##########################################################################################################################################################
|
||||||
# Wert des solcastapi-Hash zurückliefern
|
# Wert des solcastapi-Hash zurückliefern
|
||||||
# Usage:
|
# Usage:
|
||||||
@ -19020,7 +19202,7 @@ to ensure that the system configuration is correct.
|
|||||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||||
<tr><td> <b>setupWeatherDevX</b> </td><td>DWD_OpenData Device which provides meteorological data (e.g. cloud cover) </td></tr>
|
<tr><td> <b>setupWeatherDevX</b> </td><td>DWD_OpenData Device which provides meteorological data (e.g. cloud cover) </td></tr>
|
||||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device or API for the delivery of radiation data. </td></tr>
|
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device or API for the delivery of radiation data. </td></tr>
|
||||||
<tr><td> <b>setupInverterDev</b> </td><td>Device which provides PV performance data </td></tr>
|
<tr><td> <b>setupInverterDevXX</b> </td><td>Device which provides PV performance data </td></tr>
|
||||||
<tr><td> <b>setupMeterDev</b> </td><td>Device which supplies network I/O data </td></tr>
|
<tr><td> <b>setupMeterDev</b> </td><td>Device which supplies network I/O data </td></tr>
|
||||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
<tr><td> <b>setupBatteryDev</b> </td><td>Device which provides battery performance data (if available) </td></tr>
|
||||||
<tr><td> <b>setupInverterStrings</b> </td><td>Identifier of the existing plant strings </td></tr>
|
<tr><td> <b>setupInverterStrings</b> </td><td>Identifier of the existing plant strings </td></tr>
|
||||||
@ -20944,8 +21126,8 @@ to ensure that the system configuration is correct.
|
|||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<a id="SolarForecast-attr-setupInverterDev"></a>
|
<a id="SolarForecast-attr-setupInverterDev" data-pattern="setupInverterDev.*"></a>
|
||||||
<li><b>setupInverterDev <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit>
|
<li><b>setupInverterDevXX <Inverter Device Name> pv=<Readingname>:<Unit> etotal=<Readingname>:<Unit>
|
||||||
[capacity=<max. WR-Leistung>] [icon=<Day>[@<Color>][:<Night>[@<Color>]]] </b> <br><br>
|
[capacity=<max. WR-Leistung>] [icon=<Day>[@<Color>][:<Night>[@<Color>]]] </b> <br><br>
|
||||||
|
|
||||||
Specifies any Device and its Readings to deliver the current PV generation values.
|
Specifies any Device and its Readings to deliver the current PV generation values.
|
||||||
@ -20974,7 +21156,7 @@ to ensure that the system configuration is correct.
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<b>Example: </b> <br>
|
<b>Example: </b> <br>
|
||||||
attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000 icon=inverter@red:solar
|
attr <name> setupInverterDev01 STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000 icon=inverter@red:solar
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -21363,7 +21545,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
<colgroup> <col width="25%"> <col width="75%"> </colgroup>
|
||||||
<tr><td> <b>setupWeatherDevX</b> </td><td>DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert </td></tr>
|
<tr><td> <b>setupWeatherDevX</b> </td><td>DWD_OpenData Device welches meteorologische Daten (z.B. Bewölkung) liefert </td></tr>
|
||||||
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten </td></tr>
|
<tr><td> <b>setupRadiationAPI </b> </td><td>DWD_OpenData Device bzw. API zur Lieferung von Strahlungsdaten </td></tr>
|
||||||
<tr><td> <b>setupInverterDev</b> </td><td>Device welches PV Leistungsdaten liefert </td></tr>
|
<tr><td> <b>setupInverterDevXX</b> </td><td>Device welches PV Leistungsdaten liefert </td></tr>
|
||||||
<tr><td> <b>setupMeterDev</b> </td><td>Device welches Netz I/O-Daten liefert </td></tr>
|
<tr><td> <b>setupMeterDev</b> </td><td>Device welches Netz I/O-Daten liefert </td></tr>
|
||||||
<tr><td> <b>setupBatteryDev</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
<tr><td> <b>setupBatteryDev</b> </td><td>Device welches Batterie Leistungsdaten liefert (sofern vorhanden) </td></tr>
|
||||||
<tr><td> <b>setupInverterStrings</b> </td><td>Bezeichner der vorhandenen Anlagenstrings </td></tr>
|
<tr><td> <b>setupInverterStrings</b> </td><td>Bezeichner der vorhandenen Anlagenstrings </td></tr>
|
||||||
@ -23295,8 +23477,8 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<a id="SolarForecast-attr-setupInverterDev"></a>
|
<a id="SolarForecast-attr-setupInverterDev" data-pattern="setupInverterDev.*"></a>
|
||||||
<li><b>setupInverterDev <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit>
|
<li><b>setupInverterDevXX <Inverter Device Name> pv=<Readingname>:<Einheit> etotal=<Readingname>:<Einheit>
|
||||||
[capacity=<max. WR-Leistung>] [icon=<Tag>[@<Farbe>][:<Nacht>[@<Farbe>]]] </b> <br><br>
|
[capacity=<max. WR-Leistung>] [icon=<Tag>[@<Farbe>][:<Nacht>[@<Farbe>]]] </b> <br><br>
|
||||||
|
|
||||||
Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
|
Legt ein beliebiges Device und dessen Readings zur Lieferung der aktuellen PV Erzeugungswerte fest.
|
||||||
@ -23325,7 +23507,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<b>Beispiel: </b> <br>
|
<b>Beispiel: </b> <br>
|
||||||
attr <name> setupInverterDev STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000 icon=inverter@red:solar
|
attr <name> setupInverterDev01 STP5000 pv=total_pac:kW etotal=etotal:kWh capacity=5000 icon=inverter@red:solar
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user