76_SolarForecast: pull message file from GitHub Repo instead SVN
git-svn-id: https://svn.fhem.de/fhem/trunk@29643 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# 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: pull message file from GitHub Repo instead SVN
|
||||||
- change: 76_SolarForecast: add random period get message file
|
- change: 76_SolarForecast: add random period get message file
|
||||||
- bugfix: 36_Shelly: setting of attribute slat_control
|
- bugfix: 36_Shelly: setting of attribute slat_control
|
||||||
- feature: 76_SolarForecast: new special reading todayConsumption
|
- feature: 76_SolarForecast: new special reading todayConsumption
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ package FHEM::SolarForecast;
|
|||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
#use lib qw(/opt/fhem/FHEM /opt/fhem/lib); # für Syntaxcheck mit: perl -c /opt/fhem/FHEM/76_SolarForecast.pm
|
|
||||||
use POSIX;
|
use POSIX;
|
||||||
use GPUtils qw(GP_Import GP_Export); # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt
|
use GPUtils qw(GP_Import GP_Export); # wird für den Import der FHEM Funktionen aus der fhem.pl benötigt
|
||||||
use Time::HiRes qw(gettimeofday tv_interval);
|
use Time::HiRes qw(gettimeofday tv_interval);
|
||||||
@@ -160,6 +159,7 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"1.45.5" => "09.02.2025 change constant GMFILEREPEAT, GMFILERANDOM, Pull Message File from GitHub Repo ",
|
||||||
"1.45.4" => "08.02.2025 change constant GMFILEREPEAT + new constant GMFILERANDOM ",
|
"1.45.4" => "08.02.2025 change constant GMFILEREPEAT + new constant GMFILERANDOM ",
|
||||||
"1.45.3" => "06.02.2025 __readDataWeather: if no values of hour 01 (00:00+) use val of hour 24 of day before ".
|
"1.45.3" => "06.02.2025 __readDataWeather: if no values of hour 01 (00:00+) use val of hour 24 of day before ".
|
||||||
"new special reading todayConsumption ",
|
"new special reading todayConsumption ",
|
||||||
@@ -376,50 +376,81 @@ my %vNotesIntern = (
|
|||||||
|
|
||||||
## Konstanten
|
## Konstanten
|
||||||
######################
|
######################
|
||||||
use constant LPOOLLENLIM => 140; # Breitenbegrenzung der Ausgabe von List Pooldaten
|
use constant {
|
||||||
use constant KJ2KWH => 0.0002777777778; # Umrechnungsfaktor kJ in kWh
|
LPOOLLENLIM => 140, # Breitenbegrenzung der Ausgabe von List Pooldaten
|
||||||
use constant KJ2WH => 0.2777777778; # Umrechnungsfaktor kJ in Wh
|
KJ2KWH => 0.0002777777778, # Umrechnungsfaktor kJ in kWh
|
||||||
use constant WH2KJ => 3.6; # Umrechnungsfaktor Wh in kJ
|
KJ2WH => 0.2777777778, # Umrechnungsfaktor kJ in Wh
|
||||||
use constant DEFLANG => 'EN'; # default Sprache wenn nicht konfiguriert
|
WH2KJ => 3.6, # Umrechnungsfaktor Wh in kJ
|
||||||
use constant DEFMAXVAR => 1.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor (geändert V.45.0 mit Median Verfahren)
|
DEFLANG => 'EN', # default Sprache wenn nicht konfiguriert
|
||||||
use constant DEFINTERVAL => 70; # Standard Abfrageintervall
|
DEFMAXVAR => 1.5, # max. Varianz pro Tagesberechnung Autokorrekturfaktor (geändert V.45.0 mit Median Verfahren)
|
||||||
use constant SLIDENUMMAX => 3; # max. Anzahl der Arrayelemente in Schieberegistern
|
DEFINTERVAL => 70, # Standard Abfrageintervall
|
||||||
use constant SPLSLIDEMAX => 20; # max. Anzahl der Arrayelemente in Schieberegister PV Überschuß
|
SLIDENUMMAX => 3, # max. Anzahl der Arrayelemente in Schieberegistern
|
||||||
|
SPLSLIDEMAX => 20, # max. Anzahl der Arrayelemente in Schieberegister PV Überschuß
|
||||||
|
WHISTREPEAT => 851, # Wiederholungsintervall Cache File Daten schreiben
|
||||||
|
EPIECMAXCYCLES => 10, # Anzahl Einschaltzyklen (Consumer) für verbraucherspezifische Energiestück Ermittlung
|
||||||
|
|
||||||
use constant MAXWEATHERDEV => 3; # max. Anzahl Wetter Devices (Attr setupWeatherDevX)
|
MAXWEATHERDEV => 3, # max. Anzahl Wetter Devices (Attr setupWeatherDevX)
|
||||||
use constant MAXBATTERIES => 3; # maximale Anzahl der möglichen Batterien
|
MAXBATTERIES => 3, # maximale Anzahl der möglichen Batterien
|
||||||
use constant MAXCONSUMER => 16; # maximale Anzahl der möglichen Consumer (Attribut)
|
MAXCONSUMER => 16, # maximale Anzahl der möglichen Consumer (Attribut)
|
||||||
use constant MAXPRODUCER => 3; # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
MAXPRODUCER => 3, # maximale Anzahl der möglichen anderen Produzenten (Attribut)
|
||||||
use constant MAXINVERTER => 3; # maximale Anzahl der möglichen Inverter
|
MAXINVERTER => 3, # maximale Anzahl der möglichen Inverter
|
||||||
|
|
||||||
use constant MAXSOCDEF => 95; # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt
|
MAXSOCDEF => 95, # default Wert (%) auf den die Batterie maximal aufgeladen werden soll bzw. als aufgeladen gilt
|
||||||
use constant CARECYCLEDEF => 20; # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen
|
CARECYCLEDEF => 20, # default max. Anzahl Tage die zwischen der Batterieladung auf maxSoC liegen dürfen
|
||||||
use constant BATSOCCHGDAY => 5; # Batterie: prozentuale SoC Anpassung pro Tag
|
BATSOCCHGDAY => 5, # Batterie: prozentuale SoC Anpassung pro Tag
|
||||||
|
|
||||||
use constant GMFBLTO => 30; # Timeout Aholen Message File aus contrib
|
GMFBLTO => 30, # Timeout Aholen Message File aus contrib
|
||||||
use constant GMFILEREPEAT => 4200; # Base Wiederholungsuntervall Abholen Message File aus contrib
|
GMFILEREPEAT => 3600, # Base Wiederholungsuntervall Abholen Message File aus contrib
|
||||||
use constant GMFILERANDOM => 8400; # Random AddOn zu GMFILEREPEAT
|
GMFILERANDOM => 3600, # Random AddOn zu GMFILEREPEAT
|
||||||
use constant IDXLIMIT => 900000; # Notification System: Indexe > IDXLIMIT sind reserviert für Steuerungsaufgaben
|
IDXLIMIT => 900000, # Notification System: Indexe > IDXLIMIT sind reserviert für Steuerungsaufgaben
|
||||||
|
|
||||||
use constant AITRBLTO => 7200; # KI Training BlockingCall Timeout
|
AITRBLTO => 7200, # KI Training BlockingCall Timeout
|
||||||
use constant AIBCTHHLD => 0.2; # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
AIBCTHHLD => 0.2, # Schwelle der KI Trainigszeit ab der BlockingCall benutzt wird
|
||||||
use constant AITRSTARTDEF => 2; # default Stunde f. Start AI-Training
|
AITRSTARTDEF => 2, # default Stunde f. Start AI-Training
|
||||||
use constant AISTDUDEF => 1825; # default Haltezeit KI Raw Daten (Tage)
|
AISTDUDEF => 1825, # default Haltezeit KI Raw Daten (Tage)
|
||||||
use constant AISPREADUPLIM => 120; # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
AISPREADUPLIM => 120, # obere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||||
use constant AISPREADLOWLIM => 80; # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
AISPREADLOWLIM => 80, # untere Abweichungsgrenze (%) AI 'Spread' von API Prognose
|
||||||
use constant AIACCUPLIM => 130; # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
AIACCUPLIM => 130, # obere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||||
use constant AIACCLOWLIM => 70; # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
AIACCLOWLIM => 70, # untere Abweichungsgrenze (%) AI 'Accurate' von API Prognose
|
||||||
use constant AIACCTRNMIN => 5500; # Mindestanzahl KI Trainingssätze für Verwendung "KI Accurate"
|
AIACCTRNMIN => 5500, # Mindestanzahl KI Trainingssätze für Verwendung "KI Accurate"
|
||||||
use constant AISPREADTRNMIN => 7000; # Mindestanzahl KI Trainingssätze für Verwendung "KI Spreaded"
|
AISPREADTRNMIN => 7000, # Mindestanzahl KI Trainingssätze für Verwendung "KI Spreaded"
|
||||||
|
|
||||||
use constant SOLAPIREPDEF => 3600; # default Abrufintervall SolCast API (s)
|
SOLAPIREPDEF => 3600, # default Abrufintervall SolCast API (s)
|
||||||
use constant FORAPIREPDEF => 900; # default Abrufintervall ForecastSolar API (s)
|
FORAPIREPDEF => 900, # default Abrufintervall ForecastSolar API (s)
|
||||||
use constant OMETEOREPDEF => 900; # default Abrufintervall Open-Meteo API (s)
|
OMETEOREPDEF => 900, # default Abrufintervall Open-Meteo API (s)
|
||||||
use constant VRMAPIREPDEF => 300; # default Abrufintervall Victron VRM API Forecast
|
VRMAPIREPDEF => 300, # default Abrufintervall Victron VRM API Forecast
|
||||||
use constant SOLCMAXREQDEF => 50; # max. täglich mögliche Requests SolCast API
|
SOLCMAXREQDEF => 50, # max. täglich mögliche Requests SolCast API
|
||||||
use constant OMETMAXREQ => 9700; # Beschränkung auf max. mögliche Requests Open-Meteo API
|
OMETMAXREQ => 9700, # Beschränkung auf max. mögliche Requests Open-Meteo API
|
||||||
use constant LEADTIME => 3600; # relative Zeit vor Sonnenaufgang zur Freigabe API Abruf / Verbraucherplanung
|
LEADTIME => 3600, # relative Zeit vor Sonnenaufgang zur Freigabe API Abruf / Verbraucherplanung
|
||||||
use constant LAGTIME => 1800; # Nachlaufzeit relativ zu Sunset bis Sperrung API Abruf
|
LAGTIME => 1800, # Nachlaufzeit relativ zu Sunset bis Sperrung API Abruf
|
||||||
|
|
||||||
|
PRDEF => 1.0, # default Performance Ratio (PR)
|
||||||
|
STOREFFDEF => 0.9, # default Batterie Effizienz (https://www.energie-experten.org/erneuerbare-energien/photovoltaik/stromspeicher/wirkungsgrad)
|
||||||
|
TEMPCOEFFDEF => -0.45, # default Temperaturkoeffizient Pmpp (%/°C) lt. Datenblatt Solarzelle
|
||||||
|
TEMPMODINC => 25, # default Temperaturerhöhung an Solarzellen gegenüber Umgebungstemperatur bei wolkenlosem Himmel
|
||||||
|
TEMPBASEDEF => 25, # Temperatur Module bei Nominalleistung
|
||||||
|
|
||||||
|
DEFMINTIME => 60, # default Einplanungsdauer in Minuten
|
||||||
|
DEFCTYPE => 'other', # default Verbrauchertyp
|
||||||
|
DEFCMODE => 'can', # default Planungsmode der Verbraucher
|
||||||
|
DEFPOPERCENT => 1.0, # Standard % aktuelle Leistung an nominaler Leistung gemäß Typenschild
|
||||||
|
DEFHYST => 0, # default Hysterese
|
||||||
|
|
||||||
|
CAICONDEF => 'clock@gold', # default consumerAdviceIcon
|
||||||
|
FLOWGSIZEDEF => 400, # default flowGraphicSize
|
||||||
|
HISTHOURDEF => 2, # default Anzeige vorangegangene Stunden
|
||||||
|
WTHCOLDDEF => 'C7C979', # Wetter Icon Tag default Farbe
|
||||||
|
WTHCOLNDEF => 'C7C7C7', # Wetter Icon Nacht default Farbe
|
||||||
|
B1COLDEF => 'FFAC63', # default Farbe Beam 1
|
||||||
|
B1FONTCOLDEF => '0D0D0D', # default Schriftfarbe Beam 1
|
||||||
|
B2COLDEF => 'C4C4A7', # default Farbe Beam 2
|
||||||
|
B2FONTCOLDEF => '000000', # default Schriftfarbe Beam 2
|
||||||
|
B3COLDEF => 'BED6C0', # default Farbe Beam 3
|
||||||
|
B3FONTCOLDEF => '000000', # default Schriftfarbe Beam 3
|
||||||
|
B4COLDEF => 'DBDBD0', # default Farbe Beam 4
|
||||||
|
B4FONTCOLDEF => '000000', # default Schriftfarbe Beam 4
|
||||||
|
FGCDDEF => 130, # Abstand Verbrauchericons zueinander
|
||||||
|
};
|
||||||
|
|
||||||
## Standardvariablen
|
## Standardvariablen
|
||||||
######################
|
######################
|
||||||
@@ -442,39 +473,10 @@ my $dwdcatalog = $root."/FHEM/FhemUtils/DWDcat_SolarForecast";
|
|||||||
my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Export Filename für DWD Stationskatalog im gpx-Format
|
my $dwdcatgpx = $root."/FHEM/FhemUtils/DWDcat_SolarForecast.gpx"; # Export Filename für DWD Stationskatalog im gpx-Format
|
||||||
my $pvhexprtcsv = $root."/FHEM/FhemUtils/PVH_Export_SolarForecast_"; # Filename-Fragment für PV History Exportfile (wird mit Devicename ergänzt)
|
my $pvhexprtcsv = $root."/FHEM/FhemUtils/PVH_Export_SolarForecast_"; # Filename-Fragment für PV History Exportfile (wird mit Devicename ergänzt)
|
||||||
|
|
||||||
my $calcmaxd = 30; # Anzahl Tage die zur Berechnung Vorhersagekorrektur verwendet werden
|
|
||||||
my @dweattrmust = qw(TTT Neff RR1c ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
|
my @dweattrmust = qw(TTT Neff RR1c ww SunUp SunRise SunSet); # Werte die im Attr forecastProperties des Weather-DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||||
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
|
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||||
my $whistrepeat = 851; # Wiederholungsintervall Cache File Daten schreiben
|
|
||||||
|
|
||||||
my $prdef = 1.0; # default Performance Ratio (PR)
|
|
||||||
my $storeffdef = 0.9; # default Batterie Effizienz (https://www.energie-experten.org/erneuerbare-energien/photovoltaik/stromspeicher/wirkungsgrad)
|
|
||||||
my $tempcoeffdef = -0.45; # default Temperaturkoeffizient Pmpp (%/°C) lt. Datenblatt Solarzelle
|
|
||||||
my $tempmodinc = 25; # default Temperaturerhöhung an Solarzellen gegenüber Umgebungstemperatur bei wolkenlosem Himmel
|
|
||||||
my $tempbasedef = 25; # Temperatur Module bei Nominalleistung
|
|
||||||
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
|
||||||
my $defmintime = 60; # default Einplanungsdauer in Minuten
|
|
||||||
my $defctype = 'other'; # default Verbrauchertyp
|
|
||||||
my $defcmode = 'can'; # default Planungsmode der Verbraucher
|
|
||||||
my $defpopercent = 1.0; # Standard % aktuelle Leistung an nominaler Leistung gemäß Typenschild
|
|
||||||
my $defhyst = 0; # default Hysterese
|
|
||||||
|
|
||||||
my $caicondef = 'clock@gold'; # default consumerAdviceIcon
|
|
||||||
my $flowGSizedef = 400; # default flowGraphicSize
|
|
||||||
my $histhourdef = 2; # default Anzeige vorangegangene Stunden
|
|
||||||
my $wthcolddef = 'C7C979'; # Wetter Icon Tag default Farbe
|
|
||||||
my $wthcolndef = 'C7C7C7'; # Wetter Icon Nacht default Farbe
|
|
||||||
my $b1coldef = 'FFAC63'; # default Farbe Beam 1
|
|
||||||
my $b1fontcoldef = '0D0D0D'; # default Schriftfarbe Beam 1
|
|
||||||
my $b2coldef = 'C4C4A7'; # default Farbe Beam 2
|
|
||||||
my $b2fontcoldef = '000000'; # default Schriftfarbe Beam 2
|
|
||||||
my $b3coldef = 'BED6C0'; # default Farbe Beam 3
|
|
||||||
my $b3fontcoldef = '000000'; # default Schriftfarbe Beam 3
|
|
||||||
my $b4coldef = 'DBDBD0'; # default Farbe Beam 4
|
|
||||||
my $b4fontcoldef = '000000'; # default Schriftfarbe Beam 4
|
|
||||||
my $fgCDdef = 130; # Abstand Verbrauchericons zueinander
|
|
||||||
|
|
||||||
my $fgscaledef = 0.10; # Flußgrafik: Scale Normativ Icons
|
my $fgscaledef = 0.10; # Flußgrafik: Scale Normativ Icons
|
||||||
my $strokcolstddef = 'darkorange'; # Flußgrafik: Standardfarbe aktive normale Kette
|
my $strokcolstddef = 'darkorange'; # Flußgrafik: Standardfarbe aktive normale Kette
|
||||||
@@ -499,9 +501,12 @@ my $inactcoldef = 'grey';
|
|||||||
|
|
||||||
my $bPath = 'https://svn.fhem.de/trac/browser/trunk/fhem/contrib/SolarForecast/'; # Basispfad Abruf contrib SolarForecast Files
|
my $bPath = 'https://svn.fhem.de/trac/browser/trunk/fhem/contrib/SolarForecast/'; # Basispfad Abruf contrib SolarForecast Files
|
||||||
my $cfile = 'controls_solarforecast.txt'; # Controlfile Update FTUI-Files
|
my $cfile = 'controls_solarforecast.txt'; # Controlfile Update FTUI-Files
|
||||||
|
my $pPath = '?format=txt'; # Download Format
|
||||||
|
|
||||||
|
my $bghPath = 'https://raw.githubusercontent.com/nasseeder1/FHEM-SolarForecast/refs/heads/main/'; # Basispfad GitHub SolarForecast Files
|
||||||
my $msgfiletest = 'controls_solarforecast_messages_test.txt'; # TEST Input-File Notification System
|
my $msgfiletest = 'controls_solarforecast_messages_test.txt'; # TEST Input-File Notification System
|
||||||
my $msgfileprod = 'controls_solarforecast_messages_prod.txt'; # PRODUKTIVES Input-File Notification System
|
my $msgfileprod = 'controls_solarforecast_messages_prod.txt'; # PRODUKTIVES Input-File Notification System
|
||||||
my $pPath = '?format=txt'; # Download Format
|
my $pghPath = ''; # GitHub Post Pfad
|
||||||
|
|
||||||
my $messagefile = $msgfileprod;
|
my $messagefile = $msgfileprod;
|
||||||
# mögliche Debug-Module
|
# mögliche Debug-Module
|
||||||
@@ -1210,12 +1215,12 @@ my %weather_ids = (
|
|||||||
|
|
||||||
my %hef = ( # Energiedaktoren für Verbrauchertypen
|
my %hef = ( # Energiedaktoren für Verbrauchertypen
|
||||||
"heater" => { f => 1.00, m => 1.00, l => 1.00, mt => 240 },
|
"heater" => { f => 1.00, m => 1.00, l => 1.00, mt => 240 },
|
||||||
"other" => { f => 1.00, m => 1.00, l => 1.00, mt => $defmintime }, # f = Faktor Energieverbrauch in erster Stunde (wichtig auch für Kalkulation in __calcEnergyPieces !)
|
"other" => { f => 1.00, m => 1.00, l => 1.00, mt => DEFMINTIME }, # f = Faktor Energieverbrauch in erster Stunde (wichtig auch für Kalkulation in __calcEnergyPieces !)
|
||||||
"charger" => { f => 1.00, m => 1.00, l => 1.00, mt => 120 }, # m = Faktor Energieverbrauch zwischen erster und letzter Stunde
|
"charger" => { f => 1.00, m => 1.00, l => 1.00, mt => 120 }, # m = Faktor Energieverbrauch zwischen erster und letzter Stunde
|
||||||
"dishwasher" => { f => 0.45, m => 0.10, l => 0.45, mt => 180 }, # l = Faktor Energieverbrauch in letzter Stunde
|
"dishwasher" => { f => 0.45, m => 0.10, l => 0.45, mt => 180 }, # l = Faktor Energieverbrauch in letzter Stunde
|
||||||
"dryer" => { f => 0.40, m => 0.40, l => 0.20, mt => 90 }, # mt = default mintime (Minuten)
|
"dryer" => { f => 0.40, m => 0.40, l => 0.20, mt => 90 }, # mt = default mintime (Minuten)
|
||||||
"washingmachine" => { f => 0.50, m => 0.30, l => 0.40, mt => 120 },
|
"washingmachine" => { f => 0.50, m => 0.30, l => 0.40, mt => 120 },
|
||||||
"noSchedule" => { f => 1.00, m => 1.00, l => 1.00, mt => $defmintime },
|
"noSchedule" => { f => 1.00, m => 1.00, l => 1.00, mt => DEFMINTIME },
|
||||||
);
|
);
|
||||||
|
|
||||||
my %hcsr = ( # Funktiontemplate zur Erstellung optionaler Statistikreadings
|
my %hcsr = ( # Funktiontemplate zur Erstellung optionaler Statistikreadings
|
||||||
@@ -1578,8 +1583,8 @@ sub Define {
|
|||||||
singleUpdateState ( {hash => $hash, state => 'initialized', evt => 1} );
|
singleUpdateState ( {hash => $hash, state => 'initialized', evt => 1} );
|
||||||
|
|
||||||
$readyfnlist{$name} = $hash; # Registrierung in Ready-Schleife
|
$readyfnlist{$name} = $hash; # Registrierung in Ready-Schleife
|
||||||
InternalTimer (gettimeofday() + $whistrepeat + int(rand(300)), "FHEM::SolarForecast::periodicWriteMemcache", $hash, 0); # Einstieg periodisches Schreiben historische Daten
|
InternalTimer (gettimeofday() + WHISTREPEAT + int(rand(300)), "FHEM::SolarForecast::periodicWriteMemcache", $hash, 0); # Einstieg periodisches Schreiben historische Daten
|
||||||
InternalTimer (gettimeofday() + 120 + int(rand(2700)), "FHEM::SolarForecast::getMessageFileNonBlocking", $hash, 0);
|
InternalTimer (gettimeofday() + 120 + int(rand(300)), "FHEM::SolarForecast::getMessageFileNonBlocking", $hash, 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1736,7 +1741,7 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
|
|||||||
return qq{no consumer number specified} if(!$c);
|
return qq{no consumer number specified} if(!$c);
|
||||||
return qq{no valid consumer id "$c"} if(!ConsumerVal ($hash, $c, "name", ""));
|
return qq{no valid consumer id "$c"} if(!ConsumerVal ($hash, $c, "name", ""));
|
||||||
|
|
||||||
if (ConsumerVal ($hash, $c, 'type', $defctype) eq 'noSchedule') {
|
if (ConsumerVal ($hash, $c, 'type', DEFCTYPE) eq 'noSchedule') {
|
||||||
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - }.$hqtxt{scnp}{EN});
|
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - }.$hqtxt{scnp}{EN});
|
||||||
|
|
||||||
$paref->{ps} = 'noSchedule';
|
$paref->{ps} = 'noSchedule';
|
||||||
@@ -1750,7 +1755,7 @@ sub _setconsumerImmediatePlanning { ## no critic "not used"
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $startts = time;
|
my $startts = time;
|
||||||
my $mintime = ConsumerVal ($hash, $c, "mintime", $defmintime);
|
my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME);
|
||||||
|
|
||||||
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
||||||
my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
my (undef, $setshift) = sunShift ($hash, $c); # Verschiebung (Sekunden) Sonnenuntergang bei SunPath Verwendung
|
||||||
@@ -3613,15 +3618,15 @@ sub __getDWDSolarData {
|
|||||||
my $dirrad = $rad * $sdr; # Anteil Direktstrahlung an Globalstrahlung
|
my $dirrad = $rad * $sdr; # Anteil Direktstrahlung an Globalstrahlung
|
||||||
my $difrad = $rad - $dirrad; # Anteil Diffusstrahlung an Globalstrahlung
|
my $difrad = $rad - $dirrad; # Anteil Diffusstrahlung an Globalstrahlung
|
||||||
|
|
||||||
$pv = sprintf "%.1f", ((($dirrad * $af) + $difrad) * KJ2KWH * $peak * $prdef); # Rad wird in kW/m2 erwartet
|
$pv = sprintf "%.1f", ((($dirrad * $af) + $difrad) * KJ2KWH * $peak * PRDEF); # Rad wird in kW/m2 erwartet
|
||||||
}
|
}
|
||||||
else { # Flächenfaktor auf volle Rad1h anwenden
|
else { # Flächenfaktor auf volle Rad1h anwenden
|
||||||
$pv = sprintf "%.1f", ($rad * $af * KJ2KWH * $peak * $prdef);
|
$pv = sprintf "%.1f", ($rad * $af * KJ2KWH * $peak * PRDEF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { # Flächenfaktor Fix
|
else { # Flächenfaktor Fix
|
||||||
$af = ___areaFactorFix ($ti, $az); # Flächenfaktor: https://wiki.fhem.de/wiki/Ertragsprognose_PV
|
$af = ___areaFactorFix ($ti, $az); # Flächenfaktor: https://wiki.fhem.de/wiki/Ertragsprognose_PV
|
||||||
$pv = sprintf "%.1f", ($rad * $af * KJ2KWH * $peak * $prdef); # Rad wird in kW/m2 erwartet
|
$pv = sprintf "%.1f", ($rad * $af * KJ2KWH * $peak * PRDEF); # Rad wird in kW/m2 erwartet
|
||||||
}
|
}
|
||||||
|
|
||||||
$data{$name}{solcastapi}{$string}{$dateTime}{pv_estimate50} = $pv; # Startzeit wird verwendet, nicht laufende Stunde
|
$data{$name}{solcastapi}{$string}{$dateTime}{pv_estimate50} = $pv; # Startzeit wird verwendet, nicht laufende Stunde
|
||||||
@@ -4364,7 +4369,7 @@ return;
|
|||||||
# pv (Wh) = GTI * f / 1000 (kWh/m2) / 1 kW/m2 * Pnenn (kW) * PR * Korr * 1000
|
# pv (Wh) = GTI * f / 1000 (kWh/m2) / 1 kW/m2 * Pnenn (kW) * PR * Korr * 1000
|
||||||
# (GTI * f) ist bereits in dem API-Ergebnis $rad enthalten in Wh/m2
|
# (GTI * f) ist bereits in dem API-Ergebnis $rad enthalten in Wh/m2
|
||||||
# -> $rad / 1000 (kWh/m2) / 1 kW/m2 * Pnenn (kW) * PR * Korr (bezogen auf 1 Stunde)
|
# -> $rad / 1000 (kWh/m2) / 1 kW/m2 * Pnenn (kW) * PR * Korr (bezogen auf 1 Stunde)
|
||||||
# -> my $pv = sprintf "%.0f", ($rad / 1000 * $peak * $prdef);
|
# -> my $pv = sprintf "%.0f", ($rad / 1000 * $peak * PRDEF);
|
||||||
#
|
#
|
||||||
################################################################################################
|
################################################################################################
|
||||||
sub __openMeteoDWD_ApiResponse {
|
sub __openMeteoDWD_ApiResponse {
|
||||||
@@ -4499,7 +4504,7 @@ sub __openMeteoDWD_ApiResponse {
|
|||||||
|
|
||||||
my $rad1wh = $jdata->{hourly}{global_tilted_irradiance}[$k]; # Wh/m2
|
my $rad1wh = $jdata->{hourly}{global_tilted_irradiance}[$k]; # Wh/m2
|
||||||
my $rad = 10 * (sprintf "%.0f", ($rad1wh * WH2KJ) / 10); # Umrechnung Wh/m2 in kJ/m2 ->
|
my $rad = 10 * (sprintf "%.0f", ($rad1wh * WH2KJ) / 10); # Umrechnung Wh/m2 in kJ/m2 ->
|
||||||
my $pv = sprintf "%.2f", int ($rad1wh / 1000 * $peak * $prdef); # Rad wird in kWh/m2 erwartet
|
my $pv = sprintf "%.2f", int ($rad1wh / 1000 * $peak * PRDEF); # Rad wird in kWh/m2 erwartet
|
||||||
|
|
||||||
my $don = $jdata->{hourly}{is_day}[$k];
|
my $don = $jdata->{hourly}{is_day}[$k];
|
||||||
my $temp = $jdata->{hourly}{temperature_2m}[$k];
|
my $temp = $jdata->{hourly}{temperature_2m}[$k];
|
||||||
@@ -6817,7 +6822,7 @@ sub periodicWriteMemcache {
|
|||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
RemoveInternalTimer ($hash, "FHEM::SolarForecast::periodicWriteMemcache");
|
RemoveInternalTimer ($hash, "FHEM::SolarForecast::periodicWriteMemcache");
|
||||||
InternalTimer (gettimeofday() + $whistrepeat, "FHEM::SolarForecast::periodicWriteMemcache", $hash, 0);
|
InternalTimer (gettimeofday() + WHISTREPEAT, "FHEM::SolarForecast::periodicWriteMemcache", $hash, 0);
|
||||||
|
|
||||||
my (undef, $disabled, $inactive) = controller ($name);
|
my (undef, $disabled, $inactive) = controller ($name);
|
||||||
return if($disabled || $inactive);
|
return if($disabled || $inactive);
|
||||||
@@ -7974,7 +7979,7 @@ sub _collectAllRegConsumers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$hyst = $defhyst if(!$hyst);
|
$hyst = DEFHYST if(!$hyst);
|
||||||
|
|
||||||
my ($riseshift, $setshift);
|
my ($riseshift, $setshift);
|
||||||
|
|
||||||
@@ -7998,15 +8003,15 @@ sub _collectAllRegConsumers {
|
|||||||
delete $data{$name}{consumers}{$c}{icon};
|
delete $data{$name}{consumers}{$c}{icon};
|
||||||
|
|
||||||
my $rauto = $hc->{auto} // q{};
|
my $rauto = $hc->{auto} // q{};
|
||||||
my $ctype = $hc->{type} // $defctype;
|
my $ctype = $hc->{type} // DEFCTYPE;
|
||||||
|
|
||||||
$data{$name}{consumers}{$c}{name} = $consumer; # Name des Verbrauchers (Device)
|
$data{$name}{consumers}{$c}{name} = $consumer; # Name des Verbrauchers (Device)
|
||||||
$data{$name}{consumers}{$c}{alias} = $alias; # Alias des Verbrauchers (Device)
|
$data{$name}{consumers}{$c}{alias} = $alias; # Alias des Verbrauchers (Device)
|
||||||
$data{$name}{consumers}{$c}{type} = $hc->{type} // $defctype; # Typ des Verbrauchers
|
$data{$name}{consumers}{$c}{type} = $hc->{type} // DEFCTYPE; # Typ des Verbrauchers
|
||||||
$data{$name}{consumers}{$c}{power} = $hc->{power}; # Leistungsaufnahme des Verbrauchers in W
|
$data{$name}{consumers}{$c}{power} = $hc->{power}; # Leistungsaufnahme des Verbrauchers in W
|
||||||
$data{$name}{consumers}{$c}{avgenergy} = q{}; # Initialwert Energieverbrauch (evtl. Überschreiben in manageConsumerData)
|
$data{$name}{consumers}{$c}{avgenergy} = q{}; # Initialwert Energieverbrauch (evtl. Überschreiben in manageConsumerData)
|
||||||
$data{$name}{consumers}{$c}{mintime} = $hc->{mintime} // $hef{$ctype}{mt}; # Initialwert min. Einplanungsdauer (evtl. Überschreiben in manageConsumerData)
|
$data{$name}{consumers}{$c}{mintime} = $hc->{mintime} // $hef{$ctype}{mt}; # Initialwert min. Einplanungsdauer (evtl. Überschreiben in manageConsumerData)
|
||||||
$data{$name}{consumers}{$c}{mode} = $hc->{mode} // $defcmode; # Planungsmode des Verbrauchers
|
$data{$name}{consumers}{$c}{mode} = $hc->{mode} // DEFCMODE; # Planungsmode des Verbrauchers
|
||||||
$data{$name}{consumers}{$c}{oncom} = $hc->{on} // q{}; # Setter Einschaltkommando
|
$data{$name}{consumers}{$c}{oncom} = $hc->{on} // q{}; # Setter Einschaltkommando
|
||||||
$data{$name}{consumers}{$c}{offcom} = $hc->{off} // q{}; # Setter Ausschaltkommando
|
$data{$name}{consumers}{$c}{offcom} = $hc->{off} // q{}; # Setter Ausschaltkommando
|
||||||
$data{$name}{consumers}{$c}{dswitch} = $dswitch; # Switchdevice zur Kommandoausführung
|
$data{$name}{consumers}{$c}{dswitch} = $dswitch; # Switchdevice zur Kommandoausführung
|
||||||
@@ -9068,7 +9073,7 @@ sub __calcPVestimates {
|
|||||||
my $reld = $fd == 0 ? "today" : $fd == 1 ? "tomorrow" : "unknown";
|
my $reld = $fd == 0 ? "today" : $fd == 1 ? "tomorrow" : "unknown";
|
||||||
my $rr1c = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "rr1c", 0); # Gesamtniederschlag während der letzten Stunde kg/m2
|
my $rr1c = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "rr1c", 0); # Gesamtniederschlag während der letzten Stunde kg/m2
|
||||||
my $wcc = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "wcc", 0); # effektive Wolkendecke nächste Stunde X
|
my $wcc = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "wcc", 0); # effektive Wolkendecke nächste Stunde X
|
||||||
my $temp = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "temp", $tempbasedef); # vorhergesagte Temperatur Stunde X
|
my $temp = NexthoursVal ($hash, "NextHour".sprintf ("%02d",$num), "temp", TEMPBASEDEF); # vorhergesagte Temperatur Stunde X
|
||||||
my ($acu, $aln) = isAutoCorrUsed ($name);
|
my ($acu, $aln) = isAutoCorrUsed ($name);
|
||||||
|
|
||||||
$paref->{wcc} = $wcc;
|
$paref->{wcc} = $wcc;
|
||||||
@@ -9261,8 +9266,8 @@ sub ___calcPeaklossByTemp {
|
|||||||
my $wcc = $paref->{wcc} // return (0,0); # vorhergesagte Wolkendecke Stunde X
|
my $wcc = $paref->{wcc} // return (0,0); # vorhergesagte Wolkendecke Stunde X
|
||||||
my $temp = $paref->{temp} // return (0,0); # vorhergesagte Temperatur Stunde X
|
my $temp = $paref->{temp} // return (0,0); # vorhergesagte Temperatur Stunde X
|
||||||
|
|
||||||
my $modtemp = $temp + ($tempmodinc * (1 - ($wcc/100))); # kalkulierte Modultemperatur
|
my $modtemp = $temp + (TEMPMODINC * (1 - ($wcc/100))); # kalkulierte Modultemperatur
|
||||||
my $peakloss = sprintf "%.2f", $tempcoeffdef * ($modtemp - $tempbasedef) * $peak / 100;
|
my $peakloss = sprintf "%.2f", TEMPCOEFFDEF * ($modtemp - TEMPBASEDEF) * $peak / 100;
|
||||||
|
|
||||||
return ($peakloss, $modtemp);
|
return ($peakloss, $modtemp);
|
||||||
}
|
}
|
||||||
@@ -10145,7 +10150,7 @@ sub _batChargeRecmd {
|
|||||||
|
|
||||||
## SOC-Prognose
|
## SOC-Prognose
|
||||||
#################
|
#################
|
||||||
$socwh += $crel ? ($pvfc - $confc) * $storeffdef : -$confc / $storeffdef; # PV Prognose nur einbeziehen wenn Ladefreigabe
|
$socwh += $crel ? ($pvfc - $confc) * STOREFFDEF : -$confc / STOREFFDEF; # PV Prognose nur einbeziehen wenn Ladefreigabe
|
||||||
|
|
||||||
$socwh = $socwh < $lowSocwh ? $lowSocwh :
|
$socwh = $socwh < $lowSocwh ? $lowSocwh :
|
||||||
$socwh < $batoptsocwh ? $batoptsocwh : # SoC Prognose in Wh
|
$socwh < $batoptsocwh ? $batoptsocwh : # SoC Prognose in Wh
|
||||||
@@ -10606,7 +10611,7 @@ sub __calcEnergyPieces {
|
|||||||
delete $data{$name}{consumers}{$c}{epiecHist};
|
delete $data{$name}{consumers}{$c}{epiecHist};
|
||||||
delete $data{$name}{consumers}{$c}{epiecHour};
|
delete $data{$name}{consumers}{$c}{epiecHour};
|
||||||
|
|
||||||
for my $h (1..$epiecMaxCycles) {
|
for my $h (1..EPIECMAXCYCLES) {
|
||||||
delete $data{$name}{consumers}{$c}{"epiecHist_".$h};
|
delete $data{$name}{consumers}{$c}{"epiecHist_".$h};
|
||||||
delete $data{$name}{consumers}{$c}{"epiecHist_".$h."_hours"};
|
delete $data{$name}{consumers}{$c}{"epiecHist_".$h."_hours"};
|
||||||
}
|
}
|
||||||
@@ -10614,8 +10619,8 @@ sub __calcEnergyPieces {
|
|||||||
|
|
||||||
delete $data{$name}{consumers}{$c}{epieces};
|
delete $data{$name}{consumers}{$c}{epieces};
|
||||||
|
|
||||||
my $cotype = ConsumerVal ($hash, $c, "type", $defctype );
|
my $cotype = ConsumerVal ($hash, $c, "type", DEFCTYPE);
|
||||||
my $mintime = ConsumerVal ($hash, $c, "mintime", $defmintime);
|
my $mintime = ConsumerVal ($hash, $c, "mintime", DEFMINTIME);
|
||||||
|
|
||||||
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
||||||
my ($riseshift, $setshift) = sunShift ($hash, $c);
|
my ($riseshift, $setshift) = sunShift ($hash, $c);
|
||||||
@@ -10695,7 +10700,7 @@ sub ___csmSpecificEpieces {
|
|||||||
if (ConsumerVal ($hash, $c, "epiecHour", -1) < 0) { # neue Aufzeichnung
|
if (ConsumerVal ($hash, $c, "epiecHour", -1) < 0) { # neue Aufzeichnung
|
||||||
$data{$name}{consumers}{$c}{epiecStartTime} = $t;
|
$data{$name}{consumers}{$c}{epiecStartTime} = $t;
|
||||||
$data{$name}{consumers}{$c}{epiecHist} += 1;
|
$data{$name}{consumers}{$c}{epiecHist} += 1;
|
||||||
$data{$name}{consumers}{$c}{epiecHist} = 1 if(ConsumerVal ($hash, $c, "epiecHist", 0) > $epiecMaxCycles);
|
$data{$name}{consumers}{$c}{epiecHist} = 1 if(ConsumerVal ($hash, $c, "epiecHist", 0) > EPIECMAXCYCLES);
|
||||||
|
|
||||||
$ecycle = "epiecHist_".ConsumerVal ($hash, $c, "epiecHist", 0);
|
$ecycle = "epiecHist_".ConsumerVal ($hash, $c, "epiecHist", 0);
|
||||||
|
|
||||||
@@ -10729,11 +10734,11 @@ sub ___csmSpecificEpieces {
|
|||||||
if (ConsumerVal ($hash, $c, "epiecHour", 0) > 0) {
|
if (ConsumerVal ($hash, $c, "epiecHour", 0) > 0) {
|
||||||
my $hours = 0;
|
my $hours = 0;
|
||||||
|
|
||||||
for my $h (1..$epiecMaxCycles) { # durchschnittliche Betriebsstunden über alle epieces ermitteln und aufrunden
|
for my $h (1..EPIECMAXCYCLES) { # durchschnittliche Betriebsstunden über alle epieces ermitteln und aufrunden
|
||||||
$hours += ConsumerVal ($hash, $c, "epiecHist_".$h."_hours", 0);
|
$hours += ConsumerVal ($hash, $c, "epiecHist_".$h."_hours", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
my $avghours = ceil ($hours / $epiecMaxCycles);
|
my $avghours = ceil ($hours / EPIECMAXCYCLES);
|
||||||
$data{$name}{consumers}{$c}{epiecAVG_hours} = $avghours; # durchschnittliche Betriebsstunden pro Zyklus
|
$data{$name}{consumers}{$c}{epiecAVG_hours} = $avghours; # durchschnittliche Betriebsstunden pro Zyklus
|
||||||
|
|
||||||
debugLog ($paref, "epiecesCalc", qq{specificEpieces -> consumer "$c" - Average operating hours per cycle (epiecAVG_hours): $avghours});
|
debugLog ($paref, "epiecesCalc", qq{specificEpieces -> consumer "$c" - Average operating hours per cycle (epiecAVG_hours): $avghours});
|
||||||
@@ -10743,7 +10748,7 @@ sub ___csmSpecificEpieces {
|
|||||||
for my $hour (1..$avghours) { # jede Stunde durchlaufen
|
for my $hour (1..$avghours) { # jede Stunde durchlaufen
|
||||||
my $hoursE = 1;
|
my $hoursE = 1;
|
||||||
|
|
||||||
for my $h (1..$epiecMaxCycles) { # jedes epiec durchlaufen
|
for my $h (1..EPIECMAXCYCLES) { # jedes epiec durchlaufen
|
||||||
my $ecycle = "epiecHist_".$h;
|
my $ecycle = "epiecHist_".$h;
|
||||||
|
|
||||||
if (defined $data{$name}{consumers}{$c}{$ecycle}{$hour}) {
|
if (defined $data{$name}{consumers}{$c}{$ecycle}{$hour}) {
|
||||||
@@ -10800,7 +10805,7 @@ sub __planInitialSwitchTime {
|
|||||||
qq{ alias: }.ConsumerVal ($hash, $c, 'alias', ''));
|
qq{ alias: }.ConsumerVal ($hash, $c, 'alias', ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConsumerVal ($hash, $c, 'type', $defctype) eq 'noSchedule') {
|
if (ConsumerVal ($hash, $c, 'type', DEFCTYPE) eq 'noSchedule') {
|
||||||
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - }.$hqtxt{scnp}{EN});
|
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - }.$hqtxt{scnp}{EN});
|
||||||
|
|
||||||
$paref->{ps} = 'noSchedule';
|
$paref->{ps} = 'noSchedule';
|
||||||
@@ -10967,7 +10972,7 @@ sub ___doPlanning {
|
|||||||
|
|
||||||
my $mode = getConsumerPlanningMode ($hash, $c); # Planungsmode 'can' oder 'must'
|
my $mode = getConsumerPlanningMode ($hash, $c); # Planungsmode 'can' oder 'must'
|
||||||
my $calias = ConsumerVal ($hash, $c, 'alias', '');
|
my $calias = ConsumerVal ($hash, $c, 'alias', '');
|
||||||
my $mintime = ConsumerVal ($hash, $c, 'mintime', $defmintime); # Einplanungsdauer
|
my $mintime = ConsumerVal ($hash, $c, 'mintime', DEFMINTIME); # Einplanungsdauer
|
||||||
my $oldplanstate = ConsumerVal ($hash, $c, 'planstate', ''); # V. 1.35.0
|
my $oldplanstate = ConsumerVal ($hash, $c, 'planstate', ''); # V. 1.35.0
|
||||||
|
|
||||||
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - mode: $mode, mintime: $mintime, relevant method: surplus});
|
debugLog ($paref, "consumerPlanning", qq{consumer "$c" - mode: $mode, mintime: $mintime, relevant method: surplus});
|
||||||
@@ -11589,7 +11594,7 @@ sub ___switchConsumerOff {
|
|||||||
my $stopts = ConsumerVal ($hash, $c, "planswitchoff", undef); # geplante Unix Stopzeit
|
my $stopts = ConsumerVal ($hash, $c, "planswitchoff", undef); # geplante Unix Stopzeit
|
||||||
my $auto = ConsumerVal ($hash, $c, "auto", 1);
|
my $auto = ConsumerVal ($hash, $c, "auto", 1);
|
||||||
my $calias = ConsumerVal ($hash, $c, "alias", ""); # Consumer Device Alias
|
my $calias = ConsumerVal ($hash, $c, "alias", ""); # Consumer Device Alias
|
||||||
my $hyst = ConsumerVal ($hash, $c, "hysteresis", $defhyst); # Hysterese
|
my $hyst = ConsumerVal ($hash, $c, "hysteresis", DEFHYST); # Hysterese
|
||||||
|
|
||||||
my $mode = getConsumerPlanningMode ($hash, $c); # Planungsmode 'can' oder 'must'
|
my $mode = getConsumerPlanningMode ($hash, $c); # Planungsmode 'can' oder 'must'
|
||||||
my $offcom = ConsumerVal ($hash, $c, 'offcom', ''); # Set Command für "off"
|
my $offcom = ConsumerVal ($hash, $c, 'offcom', ''); # Set Command für "off"
|
||||||
@@ -11685,7 +11690,7 @@ sub ___setConsumerSwitchingState {
|
|||||||
debugLog ($paref, "consumerSwitching${c}", qq{consumer "$c" - current planning state: $simpCstat});
|
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);
|
||||||
|
|
||||||
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
if (isSunPath ($hash, $c)) { # SunPath ist in mintime gesetzt
|
||||||
my (undef, $setshift) = sunShift ($hash, $c);
|
my (undef, $setshift) = sunShift ($hash, $c);
|
||||||
@@ -13067,7 +13072,7 @@ sub entryGraphic {
|
|||||||
my $layersync = $2 // 0;
|
my $layersync = $2 // 0;
|
||||||
|
|
||||||
my $w = $width * $maxhours; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
|
my $w = $width * $maxhours; # gesammte Breite der Ausgabe , WetterIcon braucht ca. 34px
|
||||||
my $offset = -1 * AttrNum ($name, 'graphicHistoryHour', $histhourdef);
|
my $offset = -1 * AttrNum ($name, 'graphicHistoryHour', HISTHOURDEF);
|
||||||
my $dlink = qq{<a href="$::FW_ME$::FW_subdir?detail=$name">$alias</a>};
|
my $dlink = qq{<a href="$::FW_ME$::FW_subdir?detail=$name">$alias</a>};
|
||||||
|
|
||||||
if (!$gsel) {
|
if (!$gsel) {
|
||||||
@@ -13086,15 +13091,15 @@ sub entryGraphic {
|
|||||||
dstyle => qq{style='padding-left: 10px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; white-space:nowrap;'}, # TD-Style
|
dstyle => qq{style='padding-left: 10px; padding-right: 10px; padding-top: 3px; padding-bottom: 3px; white-space:nowrap;'}, # TD-Style
|
||||||
offset => $offset,
|
offset => $offset,
|
||||||
hourstyle => AttrVal ($name, 'graphicHourStyle', ''),
|
hourstyle => AttrVal ($name, 'graphicHourStyle', ''),
|
||||||
colorb1 => AttrVal ($name, 'graphicBeam1Color', $b1coldef),
|
colorb1 => AttrVal ($name, 'graphicBeam1Color', B1COLDEF),
|
||||||
colorb2 => AttrVal ($name, 'graphicBeam2Color', $b2coldef),
|
colorb2 => AttrVal ($name, 'graphicBeam2Color', B2COLDEF),
|
||||||
fcolor1 => AttrVal ($name, 'graphicBeam1FontColor', $b1fontcoldef),
|
fcolor1 => AttrVal ($name, 'graphicBeam1FontColor', B1FONTCOLDEF),
|
||||||
fcolor2 => AttrVal ($name, 'graphicBeam2FontColor', $b2fontcoldef),
|
fcolor2 => AttrVal ($name, 'graphicBeam2FontColor', B2FONTCOLDEF),
|
||||||
beam1cont => AttrVal ($name, 'graphicBeam1Content', 'pvReal'),
|
beam1cont => AttrVal ($name, 'graphicBeam1Content', 'pvReal'),
|
||||||
beam2cont => AttrVal ($name, 'graphicBeam2Content', 'pvForecast'),
|
beam2cont => AttrVal ($name, 'graphicBeam2Content', 'pvForecast'),
|
||||||
beam3cont => AttrVal ($name, 'graphicBeam3Content', ''),
|
beam3cont => AttrVal ($name, 'graphicBeam3Content', ''),
|
||||||
beam4cont => AttrVal ($name, 'graphicBeam4Content', ''),
|
beam4cont => AttrVal ($name, 'graphicBeam4Content', ''),
|
||||||
caicon => AttrVal ($name, 'consumerAdviceIcon', $caicondef), # Consumer AdviceIcon
|
caicon => AttrVal ($name, 'consumerAdviceIcon', CAICONDEF), # Consumer AdviceIcon
|
||||||
clegend => AttrVal ($name, 'consumerLegend', 'icon_top'), # Lage und Art Cunsumer Legende
|
clegend => AttrVal ($name, 'consumerLegend', 'icon_top'), # Lage und Art Cunsumer Legende
|
||||||
clink => AttrVal ($name, 'consumerLink' , 1), # Detail-Link zum Verbraucher
|
clink => AttrVal ($name, 'consumerLink' , 1), # Detail-Link zum Verbraucher
|
||||||
lotype => AttrVal ($name, 'graphicLayoutType', 'double'),
|
lotype => AttrVal ($name, 'graphicLayoutType', 'double'),
|
||||||
@@ -13106,12 +13111,12 @@ sub entryGraphic {
|
|||||||
show_night => $show_night, # alle Balken (Spalten) anzeigen ?
|
show_night => $show_night, # alle Balken (Spalten) anzeigen ?
|
||||||
show_diff => AttrVal ($name, 'graphicShowDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen
|
show_diff => AttrVal ($name, 'graphicShowDiff', 'no'), # zusätzliche Anzeige $di{} in allen Typen
|
||||||
weather => AttrNum ($name, 'graphicShowWeather', 1), # Wetter Icons anzeigen
|
weather => AttrNum ($name, 'graphicShowWeather', 1), # Wetter Icons anzeigen
|
||||||
colorw => AttrVal ($name, 'graphicWeatherColor', $wthcolddef), # Wetter Icon Farbe Tag
|
colorw => AttrVal ($name, 'graphicWeatherColor', WTHCOLDDEF), # Wetter Icon Farbe Tag
|
||||||
colorwn => AttrVal ($name, 'graphicWeatherColorNight', $wthcolndef), # Wetter Icon Farbe Nacht
|
colorwn => AttrVal ($name, 'graphicWeatherColorNight', WTHCOLNDEF), # Wetter Icon Farbe Nacht
|
||||||
wlalias => AttrVal ($name, 'alias', $name),
|
wlalias => AttrVal ($name, 'alias', $name),
|
||||||
sheader => AttrNum ($name, 'graphicHeaderShow', 1), # Anzeigen des Grafik Headers
|
sheader => AttrNum ($name, 'graphicHeaderShow', 1), # Anzeigen des Grafik Headers
|
||||||
hdrDetail => AttrVal ($name, 'graphicHeaderDetail', 'all'), # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten
|
hdrDetail => AttrVal ($name, 'graphicHeaderDetail', 'all'), # ermöglicht den Inhalt zu begrenzen, um bspw. passgenau in ftui einzubetten
|
||||||
flowgsize => CurrentVal ($hash, 'size', $flowGSizedef), # Größe Energieflußgrafik
|
flowgsize => CurrentVal ($hash, 'size', FLOWGSIZEDEF), # Größe Energieflußgrafik
|
||||||
flowgani => CurrentVal ($hash, 'animate', 1), # Animation Energieflußgrafik
|
flowgani => CurrentVal ($hash, 'animate', 1), # Animation Energieflußgrafik
|
||||||
flowgxshift => CurrentVal ($hash, 'shiftx', 0), # X-Verschiebung der Flußgrafikbox (muß negiert werden)
|
flowgxshift => CurrentVal ($hash, 'shiftx', 0), # X-Verschiebung der Flußgrafikbox (muß negiert werden)
|
||||||
flowgyshift => CurrentVal ($hash, 'shifty', 0), # Y-Verschiebung der Flußgrafikbox (muß negiert werden)
|
flowgyshift => CurrentVal ($hash, 'shifty', 0), # Y-Verschiebung der Flußgrafikbox (muß negiert werden)
|
||||||
@@ -13119,7 +13124,7 @@ sub entryGraphic {
|
|||||||
flowgconX => CurrentVal ($hash, 'showconsumerdummy', 1), # Dummyverbraucher in der Energieflußgrafik anzeigen
|
flowgconX => CurrentVal ($hash, 'showconsumerdummy', 1), # Dummyverbraucher in der Energieflußgrafik anzeigen
|
||||||
flowgconsPower => CurrentVal ($hash, 'showconsumerpower', 1), # Verbraucher Leistung in der Energieflußgrafik anzeigen
|
flowgconsPower => CurrentVal ($hash, 'showconsumerpower', 1), # Verbraucher Leistung in der Energieflußgrafik anzeigen
|
||||||
flowgconsTime => CurrentVal ($hash, 'showconsumerremaintime', 1), # Verbraucher Restlaufeit in der Energieflußgrafik anzeigen
|
flowgconsTime => CurrentVal ($hash, 'showconsumerremaintime', 1), # Verbraucher Restlaufeit in der Energieflußgrafik anzeigen
|
||||||
flowgconsDist => CurrentVal ($hash, 'consumerdist', $fgCDdef), # Abstand Verbrauchericons zueinander
|
flowgconsDist => CurrentVal ($hash, 'consumerdist', FGCDDEF), # Abstand Verbrauchericons zueinander
|
||||||
flowgh2cDist => CurrentVal ($hash, 'h2consumerdist', 0), # Erweiterung des vertikalen Abstandes Haus -> Consumer
|
flowgh2cDist => CurrentVal ($hash, 'h2consumerdist', 0), # Erweiterung des vertikalen Abstandes Haus -> Consumer
|
||||||
genpvdva => AttrVal ($name, 'ctrlGenPVdeviation', 'daily'), # Methode der Abweichungsberechnung
|
genpvdva => AttrVal ($name, 'ctrlGenPVdeviation', 'daily'), # Methode der Abweichungsberechnung
|
||||||
lang => getLang ($hash),
|
lang => getLang ($hash),
|
||||||
@@ -13220,10 +13225,10 @@ sub entryGraphic {
|
|||||||
$paref->{chartlvl} = 2; # Balkengrafik Ebene 2
|
$paref->{chartlvl} = 2; # Balkengrafik Ebene 2
|
||||||
$paref->{beam1cont} = $paref->{beam3cont};
|
$paref->{beam1cont} = $paref->{beam3cont};
|
||||||
$paref->{beam2cont} = $paref->{beam4cont};
|
$paref->{beam2cont} = $paref->{beam4cont};
|
||||||
$paref->{colorb1} = AttrVal ($name, 'graphicBeam3Color', $b3coldef);
|
$paref->{colorb1} = AttrVal ($name, 'graphicBeam3Color', B3COLDEF);
|
||||||
$paref->{colorb2} = AttrVal ($name, 'graphicBeam4Color', $b4coldef);
|
$paref->{colorb2} = AttrVal ($name, 'graphicBeam4Color', B4COLDEF);
|
||||||
$paref->{fcolor1} = AttrVal ($name, 'graphicBeam3FontColor', $b3fontcoldef);
|
$paref->{fcolor1} = AttrVal ($name, 'graphicBeam3FontColor', B3FONTCOLDEF);
|
||||||
$paref->{fcolor2} = AttrVal ($name, 'graphicBeam4FontColor', $b4fontcoldef);
|
$paref->{fcolor2} = AttrVal ($name, 'graphicBeam4FontColor', B4FONTCOLDEF);
|
||||||
$paref->{height} = AttrVal ($name, 'graphicBeamHeightLevel2', $paref->{height});
|
$paref->{height} = AttrVal ($name, 'graphicBeamHeightLevel2', $paref->{height});
|
||||||
$paref->{weather} = 0;
|
$paref->{weather} = 0;
|
||||||
|
|
||||||
@@ -15872,7 +15877,7 @@ END3
|
|||||||
|
|
||||||
my $p = $currentPower;
|
my $p = $currentPower;
|
||||||
$p = (($currentPower / $power) * 100) if ($power > 0);
|
$p = (($currentPower / $power) * 100) if ($power > 0);
|
||||||
$consumer_style = $p > $defpopercent ? "$stna active_normal" : "$stna inactive";
|
$consumer_style = $p > DEFPOPERCENT ? "$stna active_normal" : "$stna inactive";
|
||||||
my $chain_color = ""; # Farbe der Laufkette des Consumers
|
my $chain_color = ""; # Farbe der Laufkette des Consumers
|
||||||
|
|
||||||
if ($p > 0.5) {
|
if ($p > 0.5) {
|
||||||
@@ -16534,8 +16539,6 @@ sub getMessageFileNonBlocking {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log3 ($name, 4, "$name - Notification System - Message file >$messagefile< is retrieved non blocking");
|
|
||||||
|
|
||||||
my $paref = { name => $name,
|
my $paref = { name => $name,
|
||||||
block => 1
|
block => 1
|
||||||
};
|
};
|
||||||
@@ -16564,8 +16567,11 @@ sub _retrieveMessageFile {
|
|||||||
my $name = $paref->{name};
|
my $name = $paref->{name};
|
||||||
my $block = $paref->{block} // 0;
|
my $block = $paref->{block} // 0;
|
||||||
|
|
||||||
|
Log3 ($name, 4, "$name - Notification System - Message File >$messagefile< is retrieved non blocking");
|
||||||
|
Log3 ($name, 4, "$name - Notification System - Message File Source: GitHub Repository");
|
||||||
|
|
||||||
my $valid = 1;
|
my $valid = 1;
|
||||||
my ($err, $remfile) = __httpBlockingGet ($name, $bPath.$messagefile.$pPath);
|
my ($err, $remfile) = __httpBlockingGet ($name, $bghPath.$messagefile.$pghPath);
|
||||||
|
|
||||||
$remfile = q{} if($remfile =~ /No\snode\strunk\/fhem\/contrib\/SolarForecast\//xs);
|
$remfile = q{} if($remfile =~ /No\snode\strunk\/fhem\/contrib\/SolarForecast\//xs);
|
||||||
|
|
||||||
@@ -19767,7 +19773,7 @@ sub getConsumerPlanningMode {
|
|||||||
my $c = shift;
|
my $c = shift;
|
||||||
|
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
my $mode = ConsumerVal ($hash, $c, 'mode', $defcmode); # Consumer Planungsmode
|
my $mode = ConsumerVal ($hash, $c, 'mode', DEFCMODE); # Consumer Planungsmode
|
||||||
|
|
||||||
if ($mode =~ /^(?:can|must)$/xs) {
|
if ($mode =~ /^(?:can|must)$/xs) {
|
||||||
return $mode;
|
return $mode;
|
||||||
@@ -19779,16 +19785,16 @@ sub getConsumerPlanningMode {
|
|||||||
my ($err) = isDeviceValid ( { name => $hash->{NAME}, obj => $dv, method => 'string' } );
|
my ($err) = isDeviceValid ( { name => $hash->{NAME}, obj => $dv, method => 'string' } );
|
||||||
|
|
||||||
if ($err) {
|
if ($err) {
|
||||||
Log3 ($name, 1, qq{$name - ERROR - consumer >$c< - The device '$dv' in consumer key 'mode' doesn't exist. Fall back to '$defcmode' mode.});
|
Log3 ($name, 1, qq{$name - ERROR - consumer >$c< - The device '$dv' in consumer key 'mode' doesn't exist. Fall back to 'DEFCMODE' mode.});
|
||||||
return $defcmode;
|
return DEFCMODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$err = q{};
|
$err = q{};
|
||||||
$mode = ReadingsVal ($dv, $rd, '');
|
$mode = ReadingsVal ($dv, $rd, '');
|
||||||
|
|
||||||
if ($mode !~ /^(?:can|must)$/xs) {
|
if ($mode !~ /^(?:can|must)$/xs) {
|
||||||
Log3 ($name, 1, qq{$name - ERROR - consumer >$c< - The reading '$rd' of device '$dv' is invalid or doesn't contain a valid mode. Fall back to '$defcmode' mode.});
|
Log3 ($name, 1, qq{$name - ERROR - consumer >$c< - The reading '$rd' of device '$dv' is invalid or doesn't contain a valid mode. Fall back to 'DEFCMODE' mode.});
|
||||||
return $defcmode;
|
return DEFCMODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $mode;
|
return $mode;
|
||||||
@@ -19968,7 +19974,7 @@ return 0;
|
|||||||
# Funktion liefert 1 wenn Consumer logisch "eingeschaltet"
|
# Funktion liefert 1 wenn Consumer logisch "eingeschaltet"
|
||||||
# ist, d.h. wenn der Energieverbrauch über einem bestimmten
|
# ist, d.h. wenn der Energieverbrauch über einem bestimmten
|
||||||
# Schwellenwert oder der prozentuale Verbrauch über dem
|
# Schwellenwert oder der prozentuale Verbrauch über dem
|
||||||
# Defaultwert $defpopercent ist.
|
# Defaultwert DEFPOPERCENT ist.
|
||||||
#
|
#
|
||||||
# Logisch "on" schließt physisch "on" mit ein.
|
# Logisch "on" schließt physisch "on" mit ein.
|
||||||
################################################################
|
################################################################
|
||||||
@@ -20004,7 +20010,7 @@ sub isConsumerLogOn {
|
|||||||
|
|
||||||
$data{$name}{consumers}{$c}{currpowerpercent} = $currpowerpercent;
|
$data{$name}{consumers}{$c}{currpowerpercent} = $currpowerpercent;
|
||||||
|
|
||||||
if ($pcurr > $pthreshold || $currpowerpercent > $defpopercent) { # Verbraucher ist logisch aktiv
|
if ($pcurr > $pthreshold || $currpowerpercent > DEFPOPERCENT) { # Verbraucher ist logisch aktiv
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20456,7 +20462,7 @@ sub isSunPath {
|
|||||||
my $c = shift;
|
my $c = shift;
|
||||||
|
|
||||||
my $is = 0;
|
my $is = 0;
|
||||||
my $mintime = ConsumerVal ($hash, $c, 'mintime', $defmintime);
|
my $mintime = ConsumerVal ($hash, $c, 'mintime', DEFMINTIME);
|
||||||
|
|
||||||
if ($mintime =~ /SunPath/xsi) {
|
if ($mintime =~ /SunPath/xsi) {
|
||||||
$is = 1;
|
$is = 1;
|
||||||
@@ -23056,7 +23062,7 @@ to ensure that the system configuration is correct.
|
|||||||
<ul>
|
<ul>
|
||||||
<table>
|
<table>
|
||||||
<colgroup> <col width="18%"> <col width="82%"> </colgroup>
|
<colgroup> <col width="18%"> <col width="82%"> </colgroup>
|
||||||
<tr><td> <b><Icon>@<Colour></b> </td><td>Activation recommendation is represented by icon and colour (optional) (default: light_light_dim_100@gold) </td></tr>
|
<tr><td> <b><Icon>@<Colour></b> </td><td>Activation recommendation is represented by icon and colour (optional) (default: clock@gold) </td></tr>
|
||||||
<tr><td> </td><td>(the planning data is displayed as mouse-over text) </td></tr>
|
<tr><td> </td><td>(the planning data is displayed as mouse-over text) </td></tr>
|
||||||
<tr><td> <b>times</b> </td><td>the planning status and the planned switching times are displayed as text </td></tr>
|
<tr><td> <b>times</b> </td><td>the planning status and the planned switching times are displayed as text </td></tr>
|
||||||
<tr><td> <b>none</b> </td><td>no display of the planning data </td></tr>
|
<tr><td> <b>none</b> </td><td>no display of the planning data </td></tr>
|
||||||
@@ -25543,7 +25549,7 @@ die ordnungsgemäße Anlagenkonfiguration geprüft werden.
|
|||||||
<ul>
|
<ul>
|
||||||
<table>
|
<table>
|
||||||
<colgroup> <col width="18%"> <col width="82%"> </colgroup>
|
<colgroup> <col width="18%"> <col width="82%"> </colgroup>
|
||||||
<tr><td> <b><Icon>@<Farbe></b> </td><td>Aktivierungsempfehlung wird durch Icon und Farbe (optional) dargestellt (default: light_light_dim_100@gold) </td></tr>
|
<tr><td> <b><Icon>@<Farbe></b> </td><td>Aktivierungsempfehlung wird durch Icon und Farbe (optional) dargestellt (default: clock@gold) </td></tr>
|
||||||
<tr><td> </td><td>(die Planungsdaten werden als Mouse-Over Text angezeigt) </td></tr>
|
<tr><td> </td><td>(die Planungsdaten werden als Mouse-Over Text angezeigt) </td></tr>
|
||||||
<tr><td> <b>times</b> </td><td>es werden der Planungsstatus und die geplanten Schaltzeiten als Text angezeigt </td></tr>
|
<tr><td> <b>times</b> </td><td>es werden der Planungsstatus und die geplanten Schaltzeiten als Text angezeigt </td></tr>
|
||||||
<tr><td> <b>none</b> </td><td>keine Anzeige der Planungsdaten </td></tr>
|
<tr><td> <b>none</b> </td><td>keine Anzeige der Planungsdaten </td></tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user