diff --git a/fhem/CHANGED b/fhem/CHANGED
index 91fe30c53..1b6943d5a 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it
+ - change: 76_SolarForecast: extended Debug collectData for EnergyConsumption
- bugfix: 49_SSCam: some fixes API does not exist
- change: 76_SolarForecast: Attr flowGraphicControl key shift changed to
shiftx, new key shifty,
diff --git a/fhem/FHEM/76_SolarForecast.pm b/fhem/FHEM/76_SolarForecast.pm
index 306bbaba8..98cbdf17d 100644
--- a/fhem/FHEM/76_SolarForecast.pm
+++ b/fhem/FHEM/76_SolarForecast.pm
@@ -156,6 +156,8 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.37.8" => "27.11.2024 edit commref, func _searchCacheFiles for renaming Cache files when device is renamed ".
+ "_saveEnergyConsumption: extended for Debug collectData ",
"1.37.7" => "26.11.2024 Attr flowGraphicControl: key shift changed to shiftx, new key shifty ".
"change: 'trackFlex' && \$wcc >= 70 to \$wcc >= 80 ".
"obsolete Attr deleted: flowGraphicCss, flowGraphicSize, flowGraphicAnimate, flowGraphicConsumerDistance, ".
@@ -350,7 +352,7 @@ my %vNotesIntern = (
## Standardvariablen
######################
-my @da; # Readings-Store
+my @da; # zentraler Readings-Store
my $deflang = 'EN'; # default Sprache wenn nicht konfiguriert
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
my $kJtokWh = 0.0002777777778; # Umrechnungsfaktor kJ in kWh
@@ -6357,7 +6359,16 @@ sub Rename {
my $type = (split '::', __PACKAGE__)[1];
$data{$type}{$new_name} = $data{$type}{$old_name};
- delete $data{$type}{$old_name};
+ delete $data{$type}{$old_name};
+
+ my @ftd = _searchCacheFiles ($old_name);
+
+ for my $oldf (@ftd) {
+ my $newf = $oldf;
+ $newf =~ s/_SolarForecast_${old_name}/_SolarForecast_${new_name}/xsg;
+ rename ($oldf, $newf) or
+ Log3 ($new_name, 2, qq{$new_name - WARNING - File "$oldf" could not be renamed: $!});
+ }
# Log3 ($new_name, 1, qq{$new_name - Dump -> \n}. Dumper $data{$type}{$new_name});
@@ -6414,26 +6425,7 @@ sub Delete {
my $arg = shift;
my $name = $hash->{NAME};
- my @ftd = ( $pvhcache.$name,
- $pvccache.$name,
- $plantcfg.$name,
- $csmcache.$name,
- $scpicache.$name,
- $airaw.$name,
- $aitrained.$name,
- $pvhexprtcsv.$name
- );
-
- opendir (DIR, $cachedir);
-
- while (my $file = readdir (DIR)) {
- next unless (-f "$cachedir/$file");
- next unless ($file =~ /_${name}_/);
- next unless ($file =~ /_\d{4}_\d{2}_\d{2}_\d{2}_\d{2}_\d{2}$/);
- push @ftd, "$cachedir/$file";
- }
-
- closedir (DIR);
+ my @ftd = _searchCacheFiles ($name);
for my $f (@ftd) {
my $err = FileDelete ($f);
@@ -6442,7 +6434,7 @@ sub Delete {
Log3 ($name, 1, qq{$name - Message while deleting file "$f": $err});
}
else {
- Log3 ($name, 3, qq{$name - INFO - File "$f" successfully deleted.});
+ Log3 ($name, 3, qq{$name - INFO - File "$f" deleted.});
}
}
@@ -6453,6 +6445,28 @@ sub Delete {
return;
}
+#################################################################
+# Cache Files im Cache Directory suchen und als Array
+# zurückliefern
+#################################################################
+sub _searchCacheFiles {
+ my $name = shift;
+
+ my @ftd;
+
+ opendir (DIR, $cachedir);
+
+ while (my $file = readdir (DIR)) {
+ next unless (-f "$cachedir/$file");
+ next unless ($file =~ /_SolarForecast_${name}/);
+ push @ftd, "$cachedir/$file";
+ }
+
+ closedir (DIR);
+
+return @ftd;
+}
+
################################################################
# Timer schreiben Memory Struktur in File
################################################################
@@ -11847,33 +11861,40 @@ sub _saveEnergyConsumption {
my $paref = shift;
my $name = $paref->{name};
my $chour = $paref->{chour};
+ my $debug = $paref->{debug};
my $shr = sprintf "%02d", ($chour + 1);
- my $pvrl = ReadingsNum ($name, "Today_Hour".$shr."_PVreal", 0);
+ my $pvrl = ReadingsNum ($name, "Today_Hour".$shr."_PVreal", 0); # Reading enthält die Summe aller Inverterdevices
my $gfeedin = ReadingsNum ($name, "Today_Hour".$shr."_GridFeedIn", 0);
my $gcon = ReadingsNum ($name, "Today_Hour".$shr."_GridConsumption", 0);
my $batin = ReadingsNum ($name, "Today_Hour".$shr."_BatIn", 0);
my $batout = ReadingsNum ($name, "Today_Hour".$shr."_BatOut", 0);
+ my $ppreal = 0;
- my $con = $pvrl - $gfeedin + $gcon - $batin + $batout;
-
- for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
- $prn = sprintf "%02d", $prn;
- $con += ReadingsNum ($name, "Today_Hour".$shr."_PPreal".$prn, 0);
+ for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
+ $prn = sprintf "%02d", $prn;
+ $ppreal += ReadingsNum ($name, "Today_Hour".$shr."_PPreal".$prn, 0);
}
+
+ my $con = $pvrl + $ppreal - $gfeedin + $gcon - $batin + $batout;
- if (int $paref->{minute} > 30 && $con < 0) { # V1.32.0 : erst den "eingeschwungenen" Zustand mit mehreren Meßwerten auswerten
+ if (int $paref->{minute} > 30 && $con < 0) { # V1.32.0 : erst den "eingeschwungenen" Zustand mit mehreren Meßwerten auswerten
my $vl = 3;
my $pre = '- WARNING -';
- if ($paref->{debug} =~ /consumption/xs) {
+ if ($debug =~ /consumption/xs) {
$vl = 1;
$pre = 'DEBUG> - WARNING -';
}
Log3 ($name, $vl, "$name $pre The calculated Energy consumption of the house is negative. This appears to be an error. Check Readings _PVreal, _GridFeedIn, _GridConsumption, _BatIn, _BatOut of hour >$shr<");
}
-
+
+ if ($debug =~ /collectData/xs) {
+ Log3 ($name, 1, "$name DEBUG> EnergyConsumption input -> PV: $pvrl, PP: $ppreal, GridIn: $gfeedin, GridCon: $gcon, BatIn: $batin, BatOut: $batout");
+ Log3 ($name, 1, "$name DEBUG> EnergyConsumption result -> $con Wh");
+ }
+
writeToHistory ( { paref => $paref, key => 'con', val => $con, hour => $shr } );
return;
@@ -21010,11 +21031,15 @@ to ensure that the system configuration is correct.
ctrlInterval <Sekunden>
Repetition interval of the data collection.
- Regardless of the set interval, data is collected automatically a few seconds before the end and after the start
- of a full hour.
- If ctrlInterval is explicitly set to "0", no automatic data collection takes place and must be carried out
- externally with "get <name> data".
- (default: 70)
+ If ctrlInterval is explicitly set to “0”, no regular data collection takes place and must be started externally
+ with “get <name> data”.
+ (default: 70)
+
+
+ Note: Regardless of the set interval (even with “0”), data is collected automatically a few seconds
+ before the end and after the start of a full hour.
+ Furthermore, data is collected automatically when an event from a device defined as “asynchron”
+ device (consumer, meter, etc.) is received and processed.
@@ -21637,7 +21662,7 @@ to ensure that the system configuration is correct.
| If 'strings' is not specified, all defined string names are assigned to the inverter. |
feed | Defines special properties of the device's energy supply (optional). |
| If the key is not set, the device feeds the PV energy into the house's AC grid. |
- | bat - the device supplies energy exclusively to the battery |
+ | bat - Solar charger for direct battery charging. Any surplus is fed into the inverter/house network. |
| grid - the energy is fed exclusively into the public grid |
limit | Defines any active power limitation in % (optional). |
icon | Icon for displaying the inverter in the flow chart (optional) |
@@ -23376,11 +23401,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
ctrlInterval <Sekunden>
Wiederholungsintervall der Datensammlung.
- Unabhängig vom eingestellten Intervall erfolgt einige Sekunden vor dem Ende sowie nach dem Beginn einer
- vollen Stunde eine automatische Datensammlung.
- Ist ctrlInterval explizit auf "0" gesetzt, erfolgt keinerlei automatische Datensammlung und muss mit
- "get <name> data" extern erfolgen.
- (default: 70)
+ Ist ctrlInterval explizit auf "0" gesetzt, erfolgt keine regelmäßige Datensammlung und muss mit
+ "get <name> data" extern gestartet werden.
+ (default: 70)
+
+
+ Hinweis: Unabhängig vom eingestellten Intervall (auch bei "0") erfolgt einige Sekunden vor dem Ende
+ sowie nach dem Beginn einer vollen Stunde eine automatische Datensammlung.
+ Weiterhin erfolgt eine automatische Datensammlung wenn ein Event eines als "asynchron"
+ definierten Gerätes (Consumer, Meter, etc.) empfangen und verarbeitet wird.
@@ -24003,7 +24032,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| Ist 'strings' nicht angegeben, werden alle definierten Stringnamen dem Wechselrichter zugeordnet. |
feed | Definiert spezielle Eigenschaften der Energielieferung des Gerätes (optional). |
| Ist der Schlüssel nicht gesetzt, speist das Gerät die PV-Energie in das Wechselstromnetz des Hauses ein. |
- | bat - das Gerät liefert die Energie ausschließlich an die Batterie |
+ | bat - Solar-Ladegerät zur Batterie Direktladung. Ein Überschuß wird dem Inverter/Hausnetz zugeführt. |
| grid - die Energie wird ausschließlich in das öffentlich Netz eingespeist |
limit | Definiert eine eventuelle Wirkleistungsbeschränkung in % (optional). |
icon | Icon zur Darstellung des Inverters in der Flowgrafik (optional) |
diff --git a/fhem/contrib/DS_Starter/76_SolarForecast.pm b/fhem/contrib/DS_Starter/76_SolarForecast.pm
index 306bbaba8..98cbdf17d 100644
--- a/fhem/contrib/DS_Starter/76_SolarForecast.pm
+++ b/fhem/contrib/DS_Starter/76_SolarForecast.pm
@@ -156,6 +156,8 @@ BEGIN {
# Versions History intern
my %vNotesIntern = (
+ "1.37.8" => "27.11.2024 edit commref, func _searchCacheFiles for renaming Cache files when device is renamed ".
+ "_saveEnergyConsumption: extended for Debug collectData ",
"1.37.7" => "26.11.2024 Attr flowGraphicControl: key shift changed to shiftx, new key shifty ".
"change: 'trackFlex' && \$wcc >= 70 to \$wcc >= 80 ".
"obsolete Attr deleted: flowGraphicCss, flowGraphicSize, flowGraphicAnimate, flowGraphicConsumerDistance, ".
@@ -350,7 +352,7 @@ my %vNotesIntern = (
## Standardvariablen
######################
-my @da; # Readings-Store
+my @da; # zentraler Readings-Store
my $deflang = 'EN'; # default Sprache wenn nicht konfiguriert
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
my $kJtokWh = 0.0002777777778; # Umrechnungsfaktor kJ in kWh
@@ -6357,7 +6359,16 @@ sub Rename {
my $type = (split '::', __PACKAGE__)[1];
$data{$type}{$new_name} = $data{$type}{$old_name};
- delete $data{$type}{$old_name};
+ delete $data{$type}{$old_name};
+
+ my @ftd = _searchCacheFiles ($old_name);
+
+ for my $oldf (@ftd) {
+ my $newf = $oldf;
+ $newf =~ s/_SolarForecast_${old_name}/_SolarForecast_${new_name}/xsg;
+ rename ($oldf, $newf) or
+ Log3 ($new_name, 2, qq{$new_name - WARNING - File "$oldf" could not be renamed: $!});
+ }
# Log3 ($new_name, 1, qq{$new_name - Dump -> \n}. Dumper $data{$type}{$new_name});
@@ -6414,26 +6425,7 @@ sub Delete {
my $arg = shift;
my $name = $hash->{NAME};
- my @ftd = ( $pvhcache.$name,
- $pvccache.$name,
- $plantcfg.$name,
- $csmcache.$name,
- $scpicache.$name,
- $airaw.$name,
- $aitrained.$name,
- $pvhexprtcsv.$name
- );
-
- opendir (DIR, $cachedir);
-
- while (my $file = readdir (DIR)) {
- next unless (-f "$cachedir/$file");
- next unless ($file =~ /_${name}_/);
- next unless ($file =~ /_\d{4}_\d{2}_\d{2}_\d{2}_\d{2}_\d{2}$/);
- push @ftd, "$cachedir/$file";
- }
-
- closedir (DIR);
+ my @ftd = _searchCacheFiles ($name);
for my $f (@ftd) {
my $err = FileDelete ($f);
@@ -6442,7 +6434,7 @@ sub Delete {
Log3 ($name, 1, qq{$name - Message while deleting file "$f": $err});
}
else {
- Log3 ($name, 3, qq{$name - INFO - File "$f" successfully deleted.});
+ Log3 ($name, 3, qq{$name - INFO - File "$f" deleted.});
}
}
@@ -6453,6 +6445,28 @@ sub Delete {
return;
}
+#################################################################
+# Cache Files im Cache Directory suchen und als Array
+# zurückliefern
+#################################################################
+sub _searchCacheFiles {
+ my $name = shift;
+
+ my @ftd;
+
+ opendir (DIR, $cachedir);
+
+ while (my $file = readdir (DIR)) {
+ next unless (-f "$cachedir/$file");
+ next unless ($file =~ /_SolarForecast_${name}/);
+ push @ftd, "$cachedir/$file";
+ }
+
+ closedir (DIR);
+
+return @ftd;
+}
+
################################################################
# Timer schreiben Memory Struktur in File
################################################################
@@ -11847,33 +11861,40 @@ sub _saveEnergyConsumption {
my $paref = shift;
my $name = $paref->{name};
my $chour = $paref->{chour};
+ my $debug = $paref->{debug};
my $shr = sprintf "%02d", ($chour + 1);
- my $pvrl = ReadingsNum ($name, "Today_Hour".$shr."_PVreal", 0);
+ my $pvrl = ReadingsNum ($name, "Today_Hour".$shr."_PVreal", 0); # Reading enthält die Summe aller Inverterdevices
my $gfeedin = ReadingsNum ($name, "Today_Hour".$shr."_GridFeedIn", 0);
my $gcon = ReadingsNum ($name, "Today_Hour".$shr."_GridConsumption", 0);
my $batin = ReadingsNum ($name, "Today_Hour".$shr."_BatIn", 0);
my $batout = ReadingsNum ($name, "Today_Hour".$shr."_BatOut", 0);
+ my $ppreal = 0;
- my $con = $pvrl - $gfeedin + $gcon - $batin + $batout;
-
- for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
- $prn = sprintf "%02d", $prn;
- $con += ReadingsNum ($name, "Today_Hour".$shr."_PPreal".$prn, 0);
+ for my $prn (1..$maxproducer) { # V1.32.0 : Erzeugung sonstiger Producer (01..03) hinzufügen
+ $prn = sprintf "%02d", $prn;
+ $ppreal += ReadingsNum ($name, "Today_Hour".$shr."_PPreal".$prn, 0);
}
+
+ my $con = $pvrl + $ppreal - $gfeedin + $gcon - $batin + $batout;
- if (int $paref->{minute} > 30 && $con < 0) { # V1.32.0 : erst den "eingeschwungenen" Zustand mit mehreren Meßwerten auswerten
+ if (int $paref->{minute} > 30 && $con < 0) { # V1.32.0 : erst den "eingeschwungenen" Zustand mit mehreren Meßwerten auswerten
my $vl = 3;
my $pre = '- WARNING -';
- if ($paref->{debug} =~ /consumption/xs) {
+ if ($debug =~ /consumption/xs) {
$vl = 1;
$pre = 'DEBUG> - WARNING -';
}
Log3 ($name, $vl, "$name $pre The calculated Energy consumption of the house is negative. This appears to be an error. Check Readings _PVreal, _GridFeedIn, _GridConsumption, _BatIn, _BatOut of hour >$shr<");
}
-
+
+ if ($debug =~ /collectData/xs) {
+ Log3 ($name, 1, "$name DEBUG> EnergyConsumption input -> PV: $pvrl, PP: $ppreal, GridIn: $gfeedin, GridCon: $gcon, BatIn: $batin, BatOut: $batout");
+ Log3 ($name, 1, "$name DEBUG> EnergyConsumption result -> $con Wh");
+ }
+
writeToHistory ( { paref => $paref, key => 'con', val => $con, hour => $shr } );
return;
@@ -21010,11 +21031,15 @@ to ensure that the system configuration is correct.
ctrlInterval <Sekunden>
Repetition interval of the data collection.
- Regardless of the set interval, data is collected automatically a few seconds before the end and after the start
- of a full hour.
- If ctrlInterval is explicitly set to "0", no automatic data collection takes place and must be carried out
- externally with "get <name> data".
- (default: 70)
+ If ctrlInterval is explicitly set to “0”, no regular data collection takes place and must be started externally
+ with “get <name> data”.
+ (default: 70)
+
+
+ Note: Regardless of the set interval (even with “0”), data is collected automatically a few seconds
+ before the end and after the start of a full hour.
+ Furthermore, data is collected automatically when an event from a device defined as “asynchron”
+ device (consumer, meter, etc.) is received and processed.
@@ -21637,7 +21662,7 @@ to ensure that the system configuration is correct.
| If 'strings' is not specified, all defined string names are assigned to the inverter. |
feed | Defines special properties of the device's energy supply (optional). |
| If the key is not set, the device feeds the PV energy into the house's AC grid. |
- | bat - the device supplies energy exclusively to the battery |
+ | bat - Solar charger for direct battery charging. Any surplus is fed into the inverter/house network. |
| grid - the energy is fed exclusively into the public grid |
limit | Defines any active power limitation in % (optional). |
icon | Icon for displaying the inverter in the flow chart (optional) |
@@ -23376,11 +23401,15 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
ctrlInterval <Sekunden>
Wiederholungsintervall der Datensammlung.
- Unabhängig vom eingestellten Intervall erfolgt einige Sekunden vor dem Ende sowie nach dem Beginn einer
- vollen Stunde eine automatische Datensammlung.
- Ist ctrlInterval explizit auf "0" gesetzt, erfolgt keinerlei automatische Datensammlung und muss mit
- "get <name> data" extern erfolgen.
- (default: 70)
+ Ist ctrlInterval explizit auf "0" gesetzt, erfolgt keine regelmäßige Datensammlung und muss mit
+ "get <name> data" extern gestartet werden.
+ (default: 70)
+
+
+ Hinweis: Unabhängig vom eingestellten Intervall (auch bei "0") erfolgt einige Sekunden vor dem Ende
+ sowie nach dem Beginn einer vollen Stunde eine automatische Datensammlung.
+ Weiterhin erfolgt eine automatische Datensammlung wenn ein Event eines als "asynchron"
+ definierten Gerätes (Consumer, Meter, etc.) empfangen und verarbeitet wird.
@@ -24003,7 +24032,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
| Ist 'strings' nicht angegeben, werden alle definierten Stringnamen dem Wechselrichter zugeordnet. |
feed | Definiert spezielle Eigenschaften der Energielieferung des Gerätes (optional). |
| Ist der Schlüssel nicht gesetzt, speist das Gerät die PV-Energie in das Wechselstromnetz des Hauses ein. |
- | bat - das Gerät liefert die Energie ausschließlich an die Batterie |
+ | bat - Solar-Ladegerät zur Batterie Direktladung. Ein Überschuß wird dem Inverter/Hausnetz zugeführt. |
| grid - die Energie wird ausschließlich in das öffentlich Netz eingespeist |
limit | Definiert eine eventuelle Wirkleistungsbeschränkung in % (optional). |
icon | Icon zur Darstellung des Inverters in der Flowgrafik (optional) |