2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-07 23:09:26 +00:00
2024-03-05 12:14:03 +00:00

496 lines
26 KiB
Plaintext

defmod WR_ctl DOIF ################################################################################################################\
## 1 Scheduling für das Abholen der Wechselrichter Statistiken\
## Umschaltung des Schattenmanagements\
##\
20_Statistic_EnergyFlow\
{if( !([$SELF:state] eq "off") ## DOIF enabled\
and\
( [:57] ## Kurz vor jeder vollen Stunde\
)\
or [$SELF:ui_command_2] eq "20_Statistic_EnergyFlow" ## Hier wird das uiTable select ausgewertet\
) {\
\
::CommandGet(undef, "WR_2_API 20_Statistic_EnergyFlow");; ## Zuerst WR_2 und anschließend\
set_Exec("wait_Statistic",2,'::CommandGet(undef, "WR_1_API 20_Statistic_EnergyFlow")');; ## WR_1, damit die Schwarm Werte stimmen\
\
## Schattenmanagement \
if ($hour == 9) {\
::CommandSet(undef, "WR_1_API 40_02_Generator_ShadowMgmt 0");; ## Komplett aus\
}\
if ($hour == 16) {\
::CommandSet(undef, "WR_1_API 40_02_Generator_ShadowMgmt 2");; ## Im Westen unten einschalten\
}\
if ($hour == 21) {\
::CommandSet(undef, "WR_1_API 40_02_Generator_ShadowMgmt 1");; ## Schattenmanagement für den Osten vorbereiten\
}\
\
if (AttrVal("$SELF","verbose",0) >=3) {\
Log 3, "$SELF cmd_1 : Abfrage der Statistiken";;\
}\
\
set_Reading("ui_command_2","---");; ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\
## kann das Kommando nicht sofort wiederholt werden\
}\
}\
\
################################################################################################################\
## 2 Start der KI Prognose\
## Der Reading Name und das Device werden in LogDBRep_PV_KI_Prognose im executeAfterProc eingestellt\
## "/opt/fhem/python/bin/PV_KI_Prognose.py 192.168.178.40 192.168.178.40 LogDBRep_PV_KI_Prognose WR_1_ctl Yield_fc"\
##\
2_KI_Prognose\
{if( !([$SELF:state] eq "off") ## DOIF enabled\
and\
ReadingsVal("LogDBRep_PV_KI_Prognose","PV_KI_Prognose","null") eq "done" ## Die Prognose darf nicht gerade laufen !!!\
and\
(\
([05:00-22:00] and [:03] ## In der PV-Zeit jede Stunde aktualisieren\
)\
or [$SELF:ui_command_1] eq "2_KI_Prognose" ## Hier wird das uiTable select ausgewertet\
)\
) {\
\
::CommandSet(undef, "LogDBRep_PV_KI_Prognose sqlCmd call dwd_load(curdate(),'none')");;\
\
if (AttrVal("$SELF","verbose",0) >=3) {\
Log 3, "$SELF 2_KI_Prognose : Start KI Prognose";;\
}\
\
set_Reading("ui_command_1","---");; ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\
## kann das Kommando nicht sofort wiederholt werden\
}\
}\
\
################################################################################################################\
## 2 Erstellen des Diagramms im uiTable\
3_WR_ctl_Diagramm\
{if( !([$SELF:state] eq "off") ## DOIF enabled\
and [$SELF:Yield_fc0_06] ## Wenn die Prognose aktualisiert wurde\
or [$SELF:ui_command_1] eq "3_WR_ctl_Diagramm" ## Hier wird das uiTable select ausgewertet\
) {\
\
my (@out) = ("") x 2;; ## Es wird für jedes Diagramm ein Array benötigt\
my $timestamp;;\
\
for (my $j=0;;$j<=1;;$j++){ ## loop fc0 und fc1\
for (my $i=5;;$i<=21;;$i++){ ## loop für die PV-Zeit\
$timestamp = sprintf("%s_%02d:00:00", POSIX::strftime("%Y-%m-%d",localtime(time)), $i);;\
$out[$j] .= $timestamp." ".::round(::ReadingsVal("$SELF",sprintf("Yield_fc%d_%02d",$j, $i),0)/1000,2)."\n";;\
} # End $i\
} # End $j\
if (AttrVal("$SELF","verbose",0) >=3) {\
Log 3, "$SELF 3_WR_ctl_Diagramm : Werte für das Diagramm";;\
print($out[0]."\n\n");;\
print($out[1]."\n");;\
}\
## Yield_fc*_current dient nur als Trigger für die card Diagramme, damit diese im uiTable aktualisiert werden.\
::DOIF_modify_card_data("$SELF","$SELF","Yield_fc0_current","bar1day",0,$out[0]);; ## Der fc1 wird verschoben, da card nicht\
::DOIF_modify_card_data("$SELF","$SELF","Yield_fc1_current","bar1day",-86400,$out[1]);; ## den nächsten Tag anzeigen kann\
\
set_Reading("ui_command_1","---");; ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\
## kann das Kommando nicht sofort wiederholt werden\
}\
}\
\
################################################################################################################\
## 4 WR_1_API setzen der init Werte für die Berechnung des Hausverbrauches. Bei Fehlern in der Verbrauchsanzeige\
## muss man die ersten Werte des Tages gegen 00:01 aus der DB setzen. \
4_WR_1_API_init_Werte\
{if( !([$SELF:state] eq "off") ## DOIF enabled\
and\
[00:01]\
or [$SELF:ui_command_2] eq "4_WR_1_API_init_Werte" ## Hier wird das uiTable select ausgewertet\
) {\
if ($hour > 0) {\
## Achtung, der init Wert muss auf den ersten Wert des Tages korrigiert werden, dieser ist in der DB\
\
## Korrektur der Tages Werte\
my $Active_energy = ::CommandGet(undef, "LogDBRep_$SELF_SQL sqlCmdBlocking\
SELECT VALUE FROM history\
WHERE DEVICE='WR_0_KSEM'\
AND READING='Active_energy-'\
AND TIMESTAMP > curdate() - interval 1 month\
AND TIMESTAMP <= concat(curdate(),' 00:01')\
ORDER BY TIMESTAMP desc\
LIMIT 1;;") ;;\
fhem("setreading WR_1_API SW_Meter_init_FeedInGrid_Day $Active_energy");;\
\
$Active_energy = ::CommandGet(undef, "LogDBRep_$SELF_SQL sqlCmdBlocking\
SELECT VALUE FROM history\
WHERE DEVICE='WR_0_KSEM'\
AND READING='Active_energy+'\
AND TIMESTAMP > curdate() - interval 1 month\
AND TIMESTAMP <= concat(curdate(),' 00:01')\
ORDER BY TIMESTAMP desc\
LIMIT 1;;") ;;\
fhem("setreading WR_1_API SW_Meter_init_Grid_Day $Active_energy");;\
\
## Korrektur der Monats Werte\
$Active_energy = ::CommandGet(undef, "LogDBRep_$SELF_SQL sqlCmdBlocking\
SELECT VALUE FROM history\
WHERE DEVICE='WR_0_KSEM'\
AND READING='Active_energy-'\
AND TIMESTAMP > curdate() - interval 1 month\
AND TIMESTAMP <= subdate(curdate(), (day(curdate())-1))\
ORDER BY TIMESTAMP desc\
LIMIT 1;;") ;;\
fhem("setreading WR_1_API SW_Meter_init_FeedInGrid_Month $Active_energy");;\
\
$Active_energy = ::CommandGet(undef, "LogDBRep_$SELF_SQL sqlCmdBlocking\
SELECT VALUE FROM history\
WHERE DEVICE='WR_0_KSEM'\
AND READING='Active_energy+'\
AND TIMESTAMP > curdate() - interval 1 month\
AND TIMESTAMP <= LAST_DAY(SUBDATE(curdate(), INTERVAL 1 MONTH))\
ORDER BY TIMESTAMP desc\
LIMIT 1;;") ;;\
fhem("setreading WR_1_API SW_Meter_init_Grid_Month $Active_energy");;\
\
::CommandGet(undef, "WR_2_API 20_Statistic_EnergyFlow");; ## Zuerst WR_2 und anschließend\
::CommandGet(undef, "WR_1_API 20_Statistic_EnergyFlow");; ## WR_1, damit die Schwarm Werte stimmen\
\
} else {\
fhem("setreading WR_1_API SW_Meter_init_FeedInGrid_Day ".[?WR_0_KSEM:Active_energy-]);;\
fhem("setreading WR_1_API SW_Meter_init_Grid_Day ".[?WR_0_KSEM:Active_energy+]);;\
}\
\
if ($mday eq 1) {\
fhem("setreading WR_1_API SW_Meter_init_FeedInGrid_Month ".[?WR_0_KSEM:Active_energy-]);;\
fhem("setreading WR_1_API SW_Meter_init_Grid_Month ".[?WR_0_KSEM:Active_energy+]);;\
\
if ($yday eq 0) {\
fhem("setreading WR_1_API SW_Meter_init_FeedInGrid_Year ".[?WR_0_KSEM:Active_energy-]);;\
fhem("setreading WR_1_API SW_Meter_init_Grid_Year ".[?WR_0_KSEM:Active_energy+]);;\
}\
}\
\
if (AttrVal("$SELF","verbose",0) >=3) {\
Log 3, "$SELF 4_WR_1_API_init_Werte : init Werte gesetzt";;\
}\
\
set_Reading("ui_command_2","---");; ## Hier wird das uiTable select wieder zurückgesetzt, ansonsten\
## kann das Kommando nicht sofort wiederholt werden\
}\
}\
attr WR_ctl DbLogExclude .*
attr WR_ctl DbLogInclude Yield_fc0_day,Yield_fc0_middayhigh.*
attr WR_ctl comment Version 2023.06.21 12:00 \
\
Die readings Yield_fc* werden direkt vom KI Prognose Skript in die Datenbank geschrieben und müssen hier nicht extra gelogged werden.
attr WR_ctl disable 0
attr WR_ctl group PV Eigenverbrauch
attr WR_ctl icon sani_solar
attr WR_ctl room 2_PV_Steuerung,Strom->Photovoltaik
attr WR_ctl sortby 11
attr WR_ctl uiState {\
package ui_Table;;\
$TABLE = "style='width:100%;;'";;\
\
$TD{0..6}{0} = "style='border-top-style:solid;;border-bottom-style:solid;;border-left-style:solid;;border-left-width:2px;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:36%;;font-weight:bold;;'";;\
$TD{0..6}{1..4} = "style='border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:8%;;text-align:center;;'";;\
$TD{0..6}{5} = "style='border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:2px;;width:8%;;text-align:center;;'";;\
\
}\
\
"KI Prognose Kommando Auswahl<dd>Mittags Limit Inverter_Max_Power / KI Status</dd>"|\
widget([$SELF:ui_command_1],"uzsuDropDown,---,2_KI_Prognose,3_WR_ctl_Diagramm") |\
""|\
""|\
"MySQL ".[LogDBRep_PV_KI_Prognose:state]."<br> KI ".([LogDBRep_PV_KI_Prognose:state] ne "done") ? "waiting" : [LogDBRep_PV_KI_Prognose:PV_KI_Prognose]\
\
"Statistiken"|\
Yield(0)|\
Yield('Tag')|\
Yield('4h')|\
Yield('Rest')\
\
card([$SELF:Yield_fc0_current:bar1day],undef,undef,0,17,90,0,"fc0 kWh",undef,"2","130,,,,,,220").card([$SELF:Yield_fc1_current:bar1day],undef,undef,0,17,90,0,"fc1 kWh",undef,"2","130,,,,,,220")|\
"<span style=font-weight:bold>nächste 3h</span><br><br>".Yield(1)."<br>".Yield(2)."<br>".Yield(3)|\
"<span style=font-weight:bold>Vor- / Nachmittag</span><br><br>".Yield('Vormittag')."<br>".Yield('Nachmittag')|\
"<span style=font-weight:bold>Maximum</span><br><br><br>".Yield("max")."<br>".Yield("max_time")|\
"<span style=font-weight:bold>Mittagshoch</span><br><br><br>fc0 ".[$SELF:Yield_fc0_middayhigh_start]." - ".[$SELF:Yield_fc0_middayhigh_stop]."<br>fc1 ".[$SELF:Yield_fc1_middayhigh_start]." - ".[$SELF:Yield_fc1_middayhigh_stop]\
\
"WR_1 / KSEM<dd> / PV Reserve / Netz Leistung</dd>"|\
""|\
sprintf("%d W",[WR_1:SW_Total_PV_P_reserve])|\
(::ReadingsVal("WR_1","Total_Active_P_EM",0) < -10) ? "<span style='color:green'>Einspeisen</span>" : (::ReadingsVal("WR_1","Total_Active_P_EM",0) > 15)? "<span style='color:red'>Netzbezug</span>" : "<span style='color:orange'>Standby</span>"|\
sprintf("%d W",[WR_1:Total_Active_P_EM])\
\
"Ertrag aktuell<dd> / Tag / Monat / Jahr</dd>"|\
""|\
sprintf("%d kWh",::round([WR_1:SW_Yield_Daily]/1000 ,0))|\
sprintf("%d kWh",::round([WR_1:SW_Yield_Monthly]/1000 ,0))|\
sprintf("%d kWh",::round([WR_1:SW_Yield_Yearly]/1000 ,0))\
\
"Speicher<dd>Temperatur / nutzbare Ladung / Status / Leistung / akt. SOC</dd>"|\
(::ReadingsVal("WR_1_API","DigitalOutputs_ConfigurationFlags",0) == 9) ? "<span style='color:green'>Lüfter An </span><br>" : "<br>".sprintf("%.1f °C",::ReadingsVal("WR_1","Battery_temperature",0))|\
sprintf("%d Wh",::ReadingsVal("WR_1","Actual_Battery_charge_usable_P",0))|\
Status_Speicher()|\
[WR_1:Actual_Battery_charge_-minus_or_discharge_-plus_P]." W<br>".sprintf("%d %%",[WR_1:Act_state_of_charge])\
\
"WR_1_API<dd>Kommando Auswahl</dd>"|\
widget([$SELF:ui_command_2],"uzsuDropDown,---,20_Statistic_EnergyFlow,4_WR_1_API_init_Werte") |\
""|\
""|\
""
attr WR_ctl uiTable {\
package ui_Table;;\
$TABLE = "style='width:100%;;'";;\
\
$TD{0..18}{0} = "style='border-top-style:solid;;border-bottom-style:solid;;border-left-style:solid;;border-left-width:2px;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:36%;;font-weight:bold;;'";;\
$TD{0..18}{1..5} = "style='border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:1px;;width:8%;;text-align:center;;'";;\
$TD{0..18}{6} = "style='border-top-style:solid;;border-bottom-style:solid;;border-right-style:solid;;border-color:darkgreen;;border-top-width:2px;;border-bottom-width:2px;;border-right-width:2px;;width:8%;;text-align:center;;'";;\
\
sub FUNC_Status {\
my($value, $min, $colorMin, $statusMin, $colorMiddel, $statusMiddle, $max, $colorMax, $statusMax)=@_;;\
my $ret = ($value < $min)? '<span style="color:'.$colorMin.'">'.$statusMin.'</span>' : ($value > $max)? '<span style="color:'.$colorMax.'">'.$statusMax.'</span>' : '<span style="color:'.$colorMiddel.'">'.$statusMiddle.'</span>';;\
return $ret;;\
}\
\
sub Status_Speicher {\
if (::ReadingsVal("WR_1","Actual_Battery_charge_-minus_or_discharge_-plus_P",0) < -10) {\
return "<span style='color:green'>Laden</span><br>".::ReadingsVal("WR_1","State_of_EM","n/a")\
} elsif (::ReadingsVal("WR_1","Actual_Battery_charge_-minus_or_discharge_-plus_P",0) > 15) {\
return "<span style='color:red'>Entladen</span><br>".::ReadingsVal("WR_1","State_of_EM","n/a")\
} else {\
return "<span style='color:orange'>Standby</span>"."<br>".::ReadingsVal("WR_1","State_of_EM","n/a")\
}\
}\
sub Yield {\
my($i)=@_;;\
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\
\
if ($i eq "4h") {\
return sprintf("%05d 4h",::ReadingsVal("$SELF","Yield_fc0_4h",0));;\
} elsif ($i eq "Tag") {\
return sprintf("%05d Tag",::ReadingsVal("$SELF","Yield_fc0_day",0));;\
} elsif ($i eq "Rest") {\
return sprintf("%05d Rest",::ReadingsVal("$SELF","Yield_fc0_rest",0));;\
} elsif ($i eq "max") {\
return sprintf("%05d Wh",::ReadingsVal("$SELF","Yield_fc0_max",0));;\
} elsif ($i eq "max_time") {\
return ::ReadingsVal("$SELF","Yield_fc0_max_time","null");;\
} elsif ($i eq "Vormittag") {\
return sprintf("%05d Wh",::ReadingsVal("$SELF","Yield_fc0_morning",0));;\
} elsif ($i eq "Nachmittag") {\
return sprintf("%05d Wh",::ReadingsVal("$SELF","Yield_fc0_afternoon",0));;\
}\
my $j = $i + $hour;;\
if ($j > 23) {\
if ($j == 24) {$j = 0}\
elsif ($j == 25) {$j = 1}\
elsif ($j == 26) {$j = 2}\
}\
return sprintf("%02d : %05d Wh",$j,::ReadingsVal("$SELF","Yield_fc0_".sprintf("%02d",$j),0));;\
}\
\
sub WR_ctl_Format {\
my($period,$device,$reading)=@_;;\
my $value = 0;;\
\
my $DayBefore = "LogDBRep_Statistic_previous_Day";;\
my $DayPrevious = ::ReadingsTimestamp("$DayBefore",$device."_".$reading."_Day","null");;\
$DayPrevious = ($DayPrevious ne "null") ? POSIX::strftime("%Y",localtime(::time_str2num(::ReadingsTimestamp("$DayBefore",$device."_".$reading."_Day","null")))) : "null";;\
\
if ($period eq "_Dx") {\
if ($DayPrevious ne "null") {\
return " / gestern";;\
}\
}\
\
my $MonthBefore = "LogDBRep_Statistic_previous_Month";;\
my $MonthPrevious = ::ReadingsTimestamp("$MonthBefore",$device."_".$reading."_Month","null");;\
$MonthPrevious = ($MonthPrevious ne "null") ? POSIX::strftime("%Y",localtime(::time_str2num(::ReadingsTimestamp("$MonthBefore",$device."_".$reading."_Month","null")))) : "null";;\
\
if ($period eq "_Mx") {\
if ($MonthPrevious ne "null") {\
return " / Vormonat";;\
}\
}\
\
my $QuarterBefore = "LogDBRep_Statistic_previous_Quarter";;\
my $QuarterPrevious = "null";;\
if ($period eq "_Qx" or $period eq "_Quarter" or $period eq "time_Quarter") {\
foreach my $loop (1,2,3,4) {\
if (::ReadingsVal("$QuarterBefore","Q".$loop,0) eq "previous") { \
$QuarterPrevious = "Q".$loop \
}\
}\
if ($period eq "_Qx" and $QuarterPrevious ne "null") {\
return $QuarterPrevious;;\
}\
}\
\
my $YearBefore = "LogDBRep_Statistic_previous_Year";;\
my $YearPrevious = ::ReadingsTimestamp($YearBefore,$reading."_Year","null");;\
$YearPrevious = ($YearPrevious ne "null") ? POSIX::strftime("%Y",localtime(::time_str2num(::ReadingsTimestamp("$YearBefore",$reading."_Year","null")))) : "null";;\
\
if ($period eq "_Yx") {\
if ($YearPrevious ne "null") {\
return " / Vorjahr";;\
}\
}\
\
if ($period eq "_Year") {\
$YearPrevious = ::ReadingsTimestamp($YearBefore,$reading.$period,"null");;\
$YearPrevious = ($YearPrevious ne "null") ? POSIX::strftime("%Y",localtime(::time_str2num(::ReadingsTimestamp($YearBefore,$reading.$period,"null")))) : "null";;\
}\
\
if ($period eq "actual" and $reading eq "Autarky") {\
my $valA = ::ReadingsVal($device, "SW_Total_AC_Active_P",0) - ::ReadingsVal($device, "SW_Home_own_consumption_from_grid",0);;\
my $calcVal = ($valA > 0) ? ::round($valA /($valA + ::ReadingsVal($device, "SW_Home_own_consumption_from_grid",0))*100 ,0) : 0;;\
return sprintf("%3d %%",(($calcVal > 100) ? 100 : $calcVal) );;\
}\
\
if ($period eq "actual" and $reading eq "OwnConsumptionRate") {\
my $valS = ::ReadingsVal($device,"SW_Total_AC_Active_P",0);;\
my $calcVal = ($valS > 0) ? ::round((::ReadingsVal($device,"SW_Home_own_consumption_from_PV",0) +\
::ReadingsVal($device,"SW_Home_own_consumption_from_Battery",0)) / $valS * 100 ,0) : 0;;\
return sprintf("%3d %%",(($calcVal > 100) ? 100 : $calcVal) );;\
}\
\
if ($period eq "time_Day" and $reading eq "SW_Statistic_Autarky") {\
return POSIX::strftime("%H:%M",localtime(::time_str2num(::ReadingsTimestamp($device, $reading."_Day",0))))\
}\
\
if ($period eq "time_Month" and $reading eq "SW_Statistic_Autarky") {\
return POSIX::strftime("%H:%M",localtime(::time_str2num(::ReadingsTimestamp($device, $reading."_Month",0))));;\
}\
\
if ($period eq "time_Quarter") {\
if ($QuarterPrevious ne "null") {\
return POSIX::strftime("%Y-%m-%d",localtime(::time_str2num(::ReadingsTimestamp($QuarterBefore, $QuarterPrevious,0))));;\
}\
}\
\
if ($period eq "time_Year" and $reading eq "SW_Statistic_Autarky") {\
my $cy = POSIX::strftime("%H:%M",localtime(::time_str2num(::ReadingsTimestamp($device, $reading."_Year",0))));;\
$cy .= ($YearPrevious ne "null") ? " / ".$YearPrevious : "";;\
return $cy;;\
}\
\
if ($period eq "Autarky_Year" or $period eq "OwnConsumptionRate_Year") {\
$value = sprintf("%3d %%",::ReadingsVal($device,$reading."_Year",0));;\
$value .= ($YearPrevious ne "null") ? sprintf(" / %3d %%", ::ReadingsVal($YearBefore,$reading."_Year",0) ) : "";;\
return $value;;\
} elsif ($period eq "_Day") {\
if ($reading eq "SW_Statistic_Autarky" or $reading eq "SW_Statistic_OwnConsumptionRate") {\
$value = sprintf("%3d %%",::ReadingsVal($device,$reading.$period,0) );;\
$value .= ($DayPrevious ne "null") ? sprintf(" / %3d %%", ::ReadingsVal($DayBefore,$device."_".$reading.$period,0) ) : "";;\
} else {\
$value = sprintf("%04d",::ReadingsVal($device,$reading.$period,0)/1000);;\
$value .= ($DayPrevious ne "null") ? sprintf(" / %04d", ::ReadingsVal($DayBefore,$device."_".$reading.$period,0) ) : "";;\
}\
return $value;;\
} elsif ($period eq "_Month") {\
if ($reading eq "SW_Statistic_Autarky" or $reading eq "SW_Statistic_OwnConsumptionRate") {\
$value = sprintf("%3d %%",::ReadingsVal($device,$reading.$period,0) );;\
$value .= ($MonthPrevious ne "null") ? sprintf(" / %3d %%", ::ReadingsVal($MonthBefore,$device."_".$reading.$period,0) ) : "";;\
} else {\
$value = sprintf("%04d",::ReadingsVal($device,$reading.$period,0)/1000);;\
$value .= ($MonthPrevious ne "null") ? sprintf(" / %04d", ::ReadingsVal($MonthBefore,$device."_".$reading.$period,0) ) : "";;\
}\
return $value;;\
} elsif ($period eq "_Quarter") {\
$value = ($QuarterPrevious ne "null") ? sprintf("%04d", ::ReadingsVal($QuarterBefore,$QuarterPrevious."_".$reading,0) ) : "";;\
return $value;;\
} elsif ($period eq "_Year") {\
$value = sprintf("%05d",::ReadingsVal($device,$reading.$period,0)/1000);;\
$value .= ($YearPrevious ne "null") ? sprintf(" / %05d", ::ReadingsVal($YearBefore,$reading.$period,0) ) : "";;\
return $value;;\
}\
return ;;\
}\
\
}\
\
\
"Statistiken ".::POSIX::strftime("%Y-%m-%d",localtime(::time_str2num(::ReadingsTimestamp("WR_1_API", "auth_me_authenticated",0))))." in kWh"|\
"<span style=font-weight:bold>aktuell</span>"|\
"<span style=font-weight:bold>heute".WR_ctl_Format("_Dx","WR_1_API","SW_Statistic_Yield")."</span>"|\
|\
"<span style=font-weight:bold>Monat".WR_ctl_Format("_Mx","WR_1_API","SW_Statistic_Yield")."</span>"|\
"<span style=font-weight:bold>".WR_ctl_Format("_Qx","none","none")."</span>"|\
"<span style=font-weight:bold>Jahr".WR_ctl_Format("_Yx","none","SW_Statistic_Yield")."</span>"\
\
"Erzeugung PV-Total"|\
sprintf("%04d W",[WR_1:SW_Total_AC_Active_P])|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_Yield")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_Yield")|\
WR_ctl_Format("_Quarter","WR_1_API","SW_Statistic_Yield")|\
WR_ctl_Format("_Year","WR_1_API","SW_Statistic_Yield")\
\
"Bezug von PV"|\
sprintf("%04d W",[WR_1:SW_Home_own_consumption_from_Battery]+[WR_1:SW_Home_own_consumption_from_PV])|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_EnergyHomePv")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_EnergyHomePv")|\
WR_ctl_Format("_Quarter","WR_1_API","SW_Statistic_EnergyHomePv")|\
WR_ctl_Format("_Year","WR_1_API","SW_Statistic_EnergyHomePv")\
\
"Bezug von Batterie"|\
sprintf("%04d W",[WR_1:SW_Home_own_consumption_from_Battery])|\
WR_ctl_Format("_Day","WR_1_API","Statistic_EnergyHomeBat")|\
|\
WR_ctl_Format("_Month","WR_1_API","Statistic_EnergyHomeBat")|\
WR_ctl_Format("_Quarter","WR_1_API","Statistic_EnergyHomeBat")|\
WR_ctl_Format("_Year","WR_1_API","Statistic_EnergyHomeBat")\
\
"Bezug vom Netz"|\
sprintf("%04d W",([WR_1:Total_Active_P_EM] >= 0 ? ::round(::ReadingsVal("WR_1","Total_Active_P_EM",0),0) : 0) )|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_EnergyHomeGrid")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_EnergyHomeGrid")|\
WR_ctl_Format("_Quarter","WR_1_API","SW_Statistic_EnergyHomeGrid")|\
WR_ctl_Format("_Year","WR_1_API","SW_Statistic_EnergyHomeGrid")\
\
"Bezug ins Haus (Energieverbrauch)"|\
sprintf("%04d W",[WR_1:SW_Home_own_consumption_from_PV]+[WR_1:SW_Home_own_consumption_from_Battery]+[WR_1:SW_Home_own_consumption_from_grid])|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_TotalConsumption")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_TotalConsumption")|\
WR_ctl_Format("_Quarter","WR_1_API","SW_Statistic_TotalConsumption")|\
WR_ctl_Format("_Year","WR_1_API","SW_Statistic_TotalConsumption")\
\
"Einspeisung ins Netz"|\
sprintf("%04d W",([WR_1:Total_Active_P_EM] <= 0 ? abs(::round(::ReadingsVal("WR_1","Total_Active_P_EM",0),0)) : 0) )|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_EnergyHomeFeedInGrid")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_EnergyHomeFeedInGrid")|\
WR_ctl_Format("_Quarter","WR_1_API","SW_Statistic_EnergyHomeFeedInGrid")|\
WR_ctl_Format("_Year","WR_1_API","SW_Statistic_EnergyHomeFeedInGrid")\
\
"Autarkiequote"|\
WR_ctl_Format("actual","WR_1","Autarky")|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_Autarky")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_Autarky")|\
|\
WR_ctl_Format("Autarky_Year","WR_1_API","SW_Statistic_Autarky")\
\
"Eigenverbrauchsquote"|\
WR_ctl_Format("actual","WR_1","OwnConsumptionRate")|\
WR_ctl_Format("_Day","WR_1_API","SW_Statistic_OwnConsumptionRate")|\
|\
WR_ctl_Format("_Month","WR_1_API","SW_Statistic_OwnConsumptionRate")|\
|\
WR_ctl_Format("OwnConsumptionRate_Year","WR_1_API","SW_Statistic_OwnConsumptionRate")\
\
"Berechnet um"|\
|\
WR_ctl_Format("time_Day","WR_1_API","SW_Statistic_Autarky")|\
|\
WR_ctl_Format("time_Month","WR_1_API","SW_Statistic_Autarky")|\
WR_ctl_Format("time_Quarter","WR_1_API","")|\
WR_ctl_Format("time_Year","WR_1_API","SW_Statistic_Autarky")\
attr WR_ctl userReadings Yield_fc0_current:Yield_fc0_18.* { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;; ::ReadingsVal("$NAME","Yield_fc0_".sprintf("%02d",$hour),0)/1000 },\
Yield_fc1_current:Yield_fc1_18.* { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;; ::ReadingsVal("$NAME","Yield_fc1_".sprintf("%02d",$hour),0)/1000 }
attr WR_ctl verbose 3
setstate WR_ctl 2023-06-21 11:33:15 SpeicherMidday_Inverter_Max_Power 9000
setstate WR_ctl 2024-01-24 16:03:00 ui_command_1 ---
setstate WR_ctl 2024-01-24 15:57:00 ui_command_2 ---