Photovoltaik Eigenverbrauch,Bilanz,Prognose (Kostal Plenticore; KSEM; BYD HV)

Begonnen von ch.eick, 07 Oktober 2020, 16:09:12

Vorheriges Thema - Nächstes Thema

ch.eick

Hallo zusammen,
ich bin jetzt mal ganz wagemutig und stelle das PV_KI_Prognose Skript hier ein :-)

KI Prognose Teil 3 - Python KI Prognose Skript

Ihr könntet dann jetzt hier weiter testen.
Und in diesem Post muss das LogDBRep_PV_KI_Prognose Device aktualisiert werden.

In der Datenbank sind dann natürlich auch Werte zum Plotten der Ergebnisse, das kommt dann später im Post für Grafana.

Feedback bitte per PN direkt an mich, damit der Thread nicht so voll wird ;-)

Frohes Oster Wochenende
    Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Hallo zusammen,
wenn für die KI Prognose jetzt keine großen Einwände kommen, würde ich dann jetzt mal die Umstellung im WR_1
und den anderen abhängigen Devices vornehmen, sodass das ganze dann produktiv wäre. Bei der Aktion würden dann
auch die WR_*_config Devices weg fallen, da es ja keine KI Prognose Konfiguration in der Form mehr geben wird.

An der alten Solar_forecast() wird es dann von meiner Seite keine Weiterentwicklung geben, ich würde dann mal
schauen, wie man das im Wiki auf eine eigene Seite stellen kann, damit es andere noch verwenden können.

In den letzten Tagen hatte ich mich dann noch mit EVU_Tibber_connect beschäftigt, um eine Möglichkeit zum
Speicherladen im Winter vorzubereiten, das ist jetzt auch soweit durch. Die uiTable Diagramme mit card könnte ich
mir für den KI Prognose noch vorstellen.
Mein Gedanke wäre aus dem PV_Schedule, was ja auch mal überarbeitet werden sollte dann eine Art übergeordnetes Device
zu machen, wo dann z.B. die KI Prognose Werte rein könnten und mit den Diagrammen aufgewertet werden. Das Scheduling
für die Bilanzen und die Statistiken könnte dort ja auch bleiben.
Denkbar wäre auch den Status von WR_1 und WR_1_API dort zu integrieren, wodurch man dann auch Pull/Down Menüs für die
API haben könnte, ohne in das WR_1_API Device rein gehen zu müssen. Die Nostalgiker könnten ja dann trotzdem das
bisherige stateFormat weiter verwenden.

Jetzt wäre dann der richtige Zeitpunkt für weitere Ideen, damit die mit einfließen können.

VG Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Moin,
ich habe mal ein Beispiel für die Diagramme im FHEMWEB erstellt und beginne das stateFormat zu migrieren.
Auch die KI Prognose Anbindung sieht man nun als Status, damit man erkennt, wann man es nicht nochmal manuell starten kann.

Leider kann das card bisher noch nicht in die Zukunft darstellen, was jedoch eventuell mal kommen soll.
Somit ist der Tagesnamen für fc1 falsch und wird wegen der Verschiebung der Zeit als Sonntag gekennzeichnet.
Dargestellt habe ich nun die KI Prognose Yield für fc0 und fc1. Auch das Maximum finde ich recht gut gekennzeichnet.

- Im Bild sieht man nun bereits den Status der Prognose, die mit den bekannten readings jetzt im WR_ctl Device abgelegt wird.
  Hierdurch werden dann die Prognose readings aus dem WR_1 Device verschwinden.
- Die wichtigsten Kommandos Aufrufe sind über das Pull/Down Menü erreichbar
- Unterhalb der Diagramme beginnt dann der Status des WR_1_API
- Die Anzeige der aktuellen Werte wird nun nicht mehr nur alle 5 Minuten aktualisiert und passt somit zum WR_1 Device
- Auch das WR_1_API Device kann über ein Pull/Down Menü abgerufen werden. Bisher ist mir nur die Statistikabfrage
  und der Plenticore Software Reset eingefallen, was man von Zeit zu Zeit mal manuell machen würde.

Als Konsequenz würde sich daraus folgendes ergeben
- Das PV_Schedule Device entfällt, da es vom WR_ctl übernommen wird.
- Die KI Prognose erstellt immer fc0 und fc1
- Die WR_*_config entfallen, da die Konfiguration der Prognose weg fällt
  - Die Wetterstation wird nur noch im DWD Device benötigt
  - Die IP-Adressen schaue ich mir nochmal an, würden aber auch im WR_ctl abgelegt werden
- Die stateFormat vom WR_1 und WR_1_API lägen nur noch als Alternative Definition im Wiki,
  falls man mal eine abgespeckte Version haben möchte, oder die alte Implementierung behalten möchte.
- Im Wiki müsste somit noch eine Seite erstellt werden, die die alten Devices noch behält, die
  jedoch dann über kurz oder lang nicht weiter gepflegt werden.

Du darfst diesen Dateianhang nicht ansehen.

Und hier kommt noch das RAW WR_ctl Stand 20230613
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
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 Strom->Photovoltaik
attr WR_ctl sortby 11
attr WR_ctl uiTable {\
package ui_Table;;\
  $TABLE = "style='width:100%;;'";;\
\
  $TD{0..18}{0}     = "align='center' style='font-size:16px;;border-right-style:solid;;border-color:darkgreen;;border-right-width:2px;;width:26%'";;\
\
  $TD{0..18}{1} = "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:36%;;font-weight:bold;;'";;\
  $TD{0..18}{2..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..18}{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;;'";;\
\
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 $MonthBefore   = "LogDBRep_Statistic_previous_Month";;\
  my $MonthPrevious = ::ReadingsTimestamp("$MonthBefore","$device"."$reading","null");;\
       $MonthPrevious = ($MonthPrevious ne "null") ?    POSIX::strftime("%Y",localtime(::time_str2num(::ReadingsTimestamp("$MonthBefore","$device"."$reading","null")))) : "null";;\
\
  my $QuarterBefore   = "LogDBRep_Statistic_previous_Quarter";;\
  my $QuarterPrevious = "null";;\
  if ($period eq "_Qx" or $period eq "_Quarter") {\
    foreach my $loop (1,2,3,4) {\
       if (::ReadingsVal("$QuarterBefore","Q".$loop,0) eq "previous") { \
         $QuarterPrevious = "Q".$loop \
       }\
    };;\
    if ($period eq "_Qx") {\
      return " / ".$QuarterPrevious;;\
    }\
  }\
\
  my $YearBefore   = "LogDBRep_Statistic_previous_Year";;\
  my $YearPrevious = "";;\
  $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_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 ($reading eq "SW_Statistic_Autarky" or $reading eq "SW_Statistic_OwnConsumptionRate") {\
      return sprintf("%3d %%",::ReadingsVal($device,$reading.$period,0) );;\
    } elsif ($period eq "_Day") {\
      return sprintf("%04d",::ReadingsVal($device,$reading.$period,0)/1000 );;\
    } elsif ($period eq "_Month") {\
      $value  = sprintf("%04d",::ReadingsVal($device,$reading.$period,0)/1000);;\
      $value .= ($MonthPrevious ne "null") ? sprintf(" / %04d", ::ReadingsVal($MonthBefore,$device."_".$reading,0) ) : "";;\
      return $value;;\
    } elsif ($period eq "_Quarter") {\
      $period = "_Month";;\
      $value  = sprintf("%04d",::ReadingsVal($device,$reading.$period,0)/1000);;\
      $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 "null";;\
}\
\
}\
\
|"KI Prognose<dd>Kommando Auswahl</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") |\
""|\
""|\
""\
\
|"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</span>"|\
"<span style=font-weight:bold>Monat".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("_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("_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("_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("_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("_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("_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_Year","WR_1_API","SW_Statistic_Autarky")\

attr WR_ctl userReadings Yield_fc0_current:Yield_fc1_12.* { 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_12.* { 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

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Hallo zusammen,
ich habe gerade gesehen, dass die KI wohl euphorisch ist :-) und einen Wert ermittelt hat, der bei mir über der Leistungsfähigkeit des Schwarms liegt.
Da schaue ich mir das Skript nochmal an und limitiere das. Mein erster Gedanke wäre aus der DB ein Maximum der Realität abzufragen und das als Limit zu verwenden.

EDIT: Durch einen Ausfall am letzten Sonntag sind mir einige Logging Daten verloren gegangen,
      nachdem ich diese wieder rekonstruiert habe sieht die Prognose wieder gut aus.

Trotzdem habe ich noch die MySQL Procedure erweitert und das Yield Maximum pro Stunde der letzten 30 Tage ermittelt.
Das wird dann für die fc0 und fc1 Prognose in einer weiteren Spalte der dwdfull Tabelle abgelegt.
Nun füge ich noch die Limitierung in das KI Prognose Skript ein, damit uns nicht die KI über das Anlagenlimit hinaus geht.


VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Moin mal wieder :-)
Gestern habe ich mal wieder an der openWB Integration gearbeitet und die leistungsreduzierte Ladung des BEV verfeinert. Das ganze dient der 70% Ausnutzung oder halt dem Peak Shaving, wie auch immer man das nennen möchte.

1.1 Es gibt bei der openWB ein 70% beachten, dass ich bereits verwende.
    - ich schiebe dem 70% beachten dynamisch einen eigenen Basiswert unter und passe diesen zusätzlich
      nach den Großverbrauchern an.
1.2 Das ganze fußt auf die Erkennung des Mittagshoch, was ja auch so ca. die 70% Grenze als Grundlage hat.
    - Die WB steht im Status Stop und der Pushbutton 70%_An ist aktiv
    - Das BEV ist angestöpselt
    - Wird nun das Mittagshoch erreicht, startet das Laden
    - Das laden geht nun langsamer und man kann es über mehrere Tage strecken
      Achtung, es entstehen etwas höhere Ladeverluste, dafür regelt der WR aber nicht mehr ab
    - Wenn das BEV nicht mehr lädt, weil der Wunsch SOC erreicht wird, sieht man das an der
      Meldung "70%_Base 9700 sofort", also "9700 Watt" stehen zur Verfügung und können "sofort" verwendet
      werden. Das Auto entscheidet, ob die verwendet werden.

    - Nach Ablauf des Mittagshoch geht es wieder in den Status Stop und am nächsten Tag wird wieder weiter geladen

2.1 Die openWB kann den Ladestrom im Status SofortLaden auch fest drosseln.
    - Den Ladestrom kann ich im FHEM Device vorgeben (siehe Bild SofortLaden limit 32 A)
    - Wählt man dort einen gewünschten Wert aus, so geht die openWB direkt ins SofortLaden
    - Wenn die PV Leistung sinkt und [WR_1:Total_Active_P_EM] > 500 Watt Bezug hat wird auf NurPV umgeschaltet
      Die 500 Watt wurden gewählt, da manchmal der Hausspeicher etwas träge reagiert, bzw es ja immer etwas um 0 Watt schwankt.

Bei mir geht das SofortLaden immer nur mit 3P, wodurch das Lademinimum dann so um die 3500 W liegt.
Im NurPV Modus gibt es eine 1P/3P Umschaltung, die ein besseres Entlangtasten an der PV-Leistung, auch bei niedrigerer Leistung gewährleistet.

Du darfst diesen Dateianhang nicht ansehen.
In meinem Beispiel wurden 13000 Watt vom Dach geliefert und 500 Watt im Haus verbraucht.
Das 70%_An hat 9700 berechnet, wodurch dann immer noch 2800 Watt eingespeist würden. Somit kann man über mehrere Tage sein BEV laden und kommt nicht in die 70% Abregelung, die ja für Anlagen > 7000 Wp noch gültig ist.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Hallo zusammen,
ich würde dann jetzt die Testphase für die KI Prognose als beendet betrachten.
Um das nun produktiv zu verwenden müsstet Ihr das PV-Scheduling entsprechend anpassen, also die alte Prognose raus nehmen oder auskommentieren und die KI Prognose dauerhaft aktivieren.
Hier ein Beispiel im PV_Schedule
   (set LogDBRep_PV_KI_Prognose sqlCmd call dwd_load(curdate(),'none') )
##   ({Solar_forecast("LogDB","LogDBRep_PV_Forecast_SQL","WR_1","Solar_Calculation_fc","DWD_Forecast",0)})
Bei der KI Prognose ist dann auch noch das Ziel Device und die reading Basis zu verändern
executeAfterProc "/opt/fhem/python/bin/PV_KI_Prognose.py <DbLog IP-Adresse> <FHEM IP-Adresse> LogDBRep_PV_KI_Prognose WR_1 Solar_Calculation_fc"

Es könnte auch noch notwendig werden, dass die Schwellwerte, wie im Anghang markiert, angepasst werden müssen. Das hängt davon ab, ob die alte - und die neue Prognose maßgeblich voneinander abweichen. Beobachtet dazu einfach mal die PV Diagramme, ob z.B. das Mittagshoch noch passt und ob die Sommer/Winter Umschaltung zielgenau passiert.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Moin zusammen,
ich habe gerade diesen Post für das WR_ctl Device aktualisiert.
Es führt die Statusanzeigen und das PV_Schedule später zusammen.

EDIT: Im Bild sieht man nun den kompletten Status und darunter die Devices WR_1 und WR_1_API ohne das stateFormat.
  In den alten Devices habe ich das stateFormat mit der Abfrage des verbose Attributs einfach unterdrückt.
  Mit Verbose >= 3 erscheint es dann wieder, was man natürlich auch noch ändern könnte.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Hallo zusammen,
es wurden noch einige Fehler in der KI Prognose korrigiert und auch das WR_ctl im uiTable noch erweitert.

Updates sind dann hier:
- KI Prognose, das Skript im Anhang ist aktualisiert
- Beim WR_ctl wird das Mittagshoch jetzt für fc0 und fc1 angezeigt

Bisher habe ich noch keine Rückfragen bekommen, weshalb ich das WR_ctl Device noch nicht geposted habe. Entweder ich habe jetzt alle abgehängt, oder es besteht kein Bedarf, weil alles stabil läuft :-)

Heute habe ich nun den nächsten Schritt gemacht und verwende erstmalig die Ausgabe der KI Prognose im WR_1_Speicher_1_ExternControl Device. Hierfür muss man dann einige readings im WR_1_Speicher_1_ExternControl umbenennen, damit die KI Prognose, die ja in einem anderen Device liegt verwendet wird. Wenn Ihr noch nicht den Schritt zum WR_ctl Device gemacht habt, da ja keine Rückfrage für die Devinition kam, dann könnt Ihr diesen Schritt natürlich auch noch nicht machen.

Zuerst bitte das KI Prognose Skript ersetzen, da eine readings falsch oder gar nicht gesetzt wurden. Nach dem nächsten Lauf sollten alle readings im WR_ctl Device vorhanden sein. Das WR_ctl gibt es bei mir auf Anfrage, damit ich mich auf den Support vorbereiten kann.

WR_1_Speicher_1_ExternControl Änderungen
im Code
[WR_1:Solar_Calculation_fc0_day]  ==> [WR_ctl:Yield_fc0_day]
[WR_1:Solar_Calculation_fc1_day]  ==> [WR_ctl:Yield_fc1_day]
[WR_1:Solar_middayhigh_fc0_start] ==> [WR_ctl:Yield_fc0_middayhigh_start]
[WR_1:Solar_middayhigh_fc0_stop]  ==> [WR_ctl:Yield_fc0_middayhigh_stop]
[WR_1:Solar_middayhigh_fc0]       ==> [WR_ctl:Yield_fc0_middayhigh]
im uiTable
[WR_1:Solar_middayhigh_fc0_start] ==> [WR_ctl:Yield_fc0_middayhigh_start]
[WR_1:Solar_middayhigh_fc0_stop]  ==> [WR_ctl:Yield_fc0_middayhigh_stop]

VG Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Hallo zusammen,
für diejenigen, die Grafana nutzen habe ich mal eine Möglichkeit, wie man das 70% Limit anzeigen könnte.
Für Anlagen <= 7 kWp ist die Begrenzung ja nicht mehr relevant und man würde damit eine Linie im Diagramm bekommen, mit der man sieht wieviel mehr man jetzt einspeist.
Du darfst diesen Dateianhang nicht ansehen.
Mit dem Grafana Select werden Werte oberhalb des alten Limits raus gesucht und durch einen Fixen Wert mit dem Limit überschrieben, es entsteht somit im Diagramm eine waagerechte Linie und alles oberhalb der Linie bis zum SW_Total_AC_Active_P ist das was man mehr einspeisen konnt. Der Hausverbrauch ist dabei bereits gedeckt.
SELECT
  $__timeGroupAlias(TIMESTAMP,$__interval,previous),
  <hier kommt das alte Limit, als positiver Wert, hin> AS "EVU Limit"
FROM history
WHERE
  $__timeFilter(TIMESTAMP) AND
  DEVICE = 'WR_1' AND
  READING = 'Total_Active_P_EM' AND
  VALUE < <hier kommt das alte Limit, als negativer Wert, hin>
GROUP BY 1
ORDER BY $__timeGroup(TIMESTAMP,$__interval,previous)
Für die Darstellung des Limits habe ich jetzt nur Punkte gewählt, da es bei Schwankungen ja auch nur temporäte Überschreitungen gibt, wo dann eine Linie ein falsches Bild liefert.
Auch sollte man dazu im Diagramm nur Total_Active_P_EM_to_Grid und nicht wie im oberen Diagramm SW_Total_AC_Active_P verwenden.
Du darfst diesen Dateianhang nicht ansehen.
Alias or regex "EVU Limit"
Lines: false
Points: true
Points Radius: 1

Hier noch ein MySQL SELECT um die wh zu berechnen.
Der Wert 4900 ist durch das eigenen Limit zu ersetzen.
Grundlage ist ein minütliches Logging der wh und die Annahme, dass es in der Minute keine Schwankung
gegeben hat, es ist somit nur eine Näherung.
-- Berechnung der wh oberhalb der 70%
SELECT cast(sum(VALUE)/60 AS decimal (6,2) ) from
  (
   SELECT TIMESTAMP, VALUE + 4900 AS VALUE
   FROM history
     WHERE
      DEVICE = 'WR_1' AND
      READING = 'Total_Active_P_EM' AND
      VALUE < -4900 AND
      TIMESTAMP > curdate()
  ) x1
;

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick


ch.eick

Hallo zusammen,
beim Astro Device ist ein kleines Problem aufgetreten, da das reading SunRise nicht garantiert einmal pro Tag aktualisiert wird. Deshalb wird nun ObsDate verwendet und Ihr müsstest dies im Astro Device korrigieren.

In diesem "KI Prognose Teil 1 - DWD und Astro Daten sammeln", ist die Änderung bereits eingetragen.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

ch.eick

Da nun einige das WR_ctl bereits im Einsatz haben, stelle ich die RAW Definition nun mal hier zur Verfügung.
Es wurde auch noch ein kleiner Fehler im uiTable korrigiert, der jetzt die Nachtstunden richtig mit 0|1|2 anzeigt, wenn der Tageswechsel ansteht.

Falls Ihr noch Ideen/Wünsche für die direkte Kommandoauswahl in den Pull Down Menüs habt, so lasst es mich wissen. Das Ziel wäre es, sowenig wie möglich in die einzelnen Devices direkt rein zu gehen und alle wiederkehrenden Dinge direkt im WR_ctl auswählen zu können.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

killah78

Hi Christian,
kurze Frage zu Yield. Du hattest ja bereits geschrieben, dass auch Yield gezählt wird, wenn die Batterie entladen wird. Nutzt du denn auch AC-seitiges Laden? Denn dann wird doppelt gezählt. Einmal im WR2 beim Etrag, und wenn die Energie dann im WR1 zum laden genutzt wird, wird sie später beim Entladen im WR1 erneut als Yield gezählt. Da habe ich bei mir immer die Differenz von Battery_Total_AC_ChargeEnergy_gridToBattery abgezogen.

Ich stelle meine Devices gerade laut Wiki um, hatte vorher eigene Namensgebungen, daher konnte ich das nicht alles so nachziehen. Dabei ist mir das jetzt aufgefallen. Ist das Wiki ansonsten aktuell? Bis auf die KI-Prognose? Die ich jetzt natürlich auch noch testen will. :-D

PS: Du machst einen sehr tollen Job hier für uns. Daumen hoch

Gruss

ch.eick

Zitat von: killah78 am 14 Juni 2023, 10:58:53Hi Christian,
kurze Frage zu Yield. Du hattest ja bereits geschrieben, dass auch Yield gezählt wird, wenn die Batterie entladen wird. Nutzt du denn auch AC-seitiges Laden? Denn dann wird doppelt gezählt. Einmal im WR2 beim Etrag, und wenn die Energie dann im WR1 zum laden genutzt wird, wird sie später beim Entladen im WR1 erneut als Yield gezählt. Da habe ich bei mir immer die Differenz von Battery_Total_AC_ChargeEnergy_gridToBattery abgezogen.

Ich stelle meine Devices gerade laut Wiki um, hatte vorher eigene Namensgebungen, daher konnte ich das nicht alles so nachziehen. Dabei ist mir das jetzt aufgefallen. Ist das Wiki ansonsten aktuell? Bis auf die KI-Prognose? Die ich jetzt natürlich auch noch testen will. :-D
Im Wiki habe ich noch nicht die letzten Versionen aus dem Forums Thread drin, da ich zuerst noch eine Art Archiv für die alten Devices im Wiki anlegen muss.

Hmm, da hast Du recht.

Für die KI Prognose rechne ich jedoch die Ladung des Speichers komplett raus, wodurch der bereinigte Yield dann stimmen sollte.
        TIMESTAMP         yield_fc0  WR   Speicher  yield_bereinigt
    2023-06-14 10:00:00    10371    9434    383     9817
    2023-06-14 09:00:00    8460     7134    339     7473
    2023-06-14 08:00:00    6238     5246     -3     5243
    2023-06-13 18:00:00    3788     6356     -4     6352
    2023-06-13 17:00:00    6352     8603     -4     8599
    2023-06-13 16:00:00    9168     10794    -3    10791
    2023-06-13 15:00:00    10791    12557    -3    12554
    2023-06-13 14:00:00    12507    13307    253    13560
    2023-06-13 13:00:00    12913    13369    485    13854
    2023-06-13 12:00:00    12273    12799    548    13347
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick