76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support

Begonnen von DS_Starter, 11 Februar 2024, 14:11:00

Vorheriges Thema - Nächstes Thema

DS_Starter

@Dieter,

die generellen Anlagenparameter müssen natürlich stimmen, aber da gehe ich davon aus.
OpenMeteo ist eigentlich eine feine Sache, insbesondere OpenMeteoDWD_D2-API läuft bei mir auch sehr gut.
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

dieter114

@Heiko
genau! Ich verwende die, und die waren bei mir auch immer recht zuverlässig.
Warum nun auf einmal so gravierende Abweichungen sind, verstehe ich nicht.
RPi II+III+V,OWX,div.1W Module,HM Zisterne,div. CUL, sduino MAPLESDuino(adv), div ESPEasy, div Tasmota, MQTT2Server,WU-Upload,TabletUI,Poolsteuerung mit fhem, Fronius, BYD Solaranlage

DS_Starter

#5402
Unser System bzw. die Eingangsparameter und Kanäle sind hoch dynamisch. Wir müssen auch mal damit leben, dass es Phasen der ungenügenden Realitätsnähe gibt. Was wir hier machen ist ein Spiel mit Wahrscheinlichkeiten, die überwiegend gut getroffen werden aber auch mal - aus verschiedensten Gründen - (evtl. völlig) daneben liegen können.
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

300P

Zitat von: DS_Starter am 15 März 2026, 11:48:03@300P,

ZitatDie andere Sache ... zeige mal bitte den Wert von pvInverterCapSum  aus "get .. valCurrent".
Problem erkannt ... Problem gebannt  ;)  Liegt im contrib.
Leider erst nach neuem Training aktiviert.

Macht nix - mir ist eigentlich der R2 zu tief - hätte so oder so nochmals trainiert bis er in Richtung 0.7 kommt....


Zitat von: DS_Starter am 15 März 2026, 11:48:03@300P,
ZitatDie Peaks kommen (glaub ich) eher von der Wärmepumpe bei der 2-maligen täglichen WW-Aufbereitung
Ja durchaus. Die Rekalibrierung benötigt einen rmse_rel_ratio und bias_var unter einem vorgebénen Schwellenwert.
Sonst ändert man auf einen neuen Bias der zu sehr von den Ausreißern geprägt ist. Die Schwellenwerte beobachte ich aber weiter.

=>> Könntest du evtl. als attr doch (statt der internen Ermittlungen für die möglichen WP-Modi heating/hot_water/defrost/cool/off) diese zum Überschreiben der interne (soweit vorhanden) einbringen / nutzen ?

Hier schon mal meine (stark abgekupferten) Codezeilen vom Anfang Februar als "Anreiz" die ich genutzt hatte...

Attribute anlegen:
#+ 300P
#+
################################################################
#                      Attr setupHPDev pu
################################################################
sub _attrHPDev {                   ## no critic "not used"
  my $paref = shift;
  my $name  = $paref->{name};
  my $aVal  = $paref->{aVal};
  my $aName = $paref->{aName};
  return if(!$init_done);

  my $hash = $defs{$name};
  my $valid = {
      hpspf             => { comp => '',          act => 0 }, ##+ noch nicht aktiv
      hptempflow        => { comp => '',          act => 0 }, ##+ noch nicht aktiv
      hptempreturn      => { comp => '',          act => 0 }, ##+ noch nicht aktiv
      hpmodeheat        => { comp => '',          act => 0 }, ##+
      hpmodehwater      => { comp => '',          act => 0 }, ##+
      hpmodedefrost     => { comp => '',          act => 0 }, ##+
      hpmodeoff         => { comp => '',          act => 0 }, ##+
      hpmodecool        => { comp => '',          act => 0 }, ##+
      hpmodepool        => { comp => '',          act => 0 }, ##+
      hpmodepoolheat    => { comp => '',          act => 0 }, ##+
  };
    my ($a, $h) = parseParams ($aVal);

  if ($paref->{cmd} eq 'set') {
      for my $key (keys %{$h}) {
          return 'The keys entered must not contain square brackets [...]' if($key =~ /[\[\]]+/xs);           # Absturzschutz!

          if (!grep /^$key$/, keys %{$valid}) {
              return qq{The key '$key' is not a valid key in attribute '$aName'};
          }
      }

      for my $akey (keys %{$h}) {         
          my $comp = $valid->{$akey}{comp};

          if ($comp && $h->{$akey} !~ /^$comp$/xs) {
              return "The key '$akey=$h->{$akey}' is not specified correctly. Please refer to the command reference.";
          }
         
          my ($dv, $rd, $regex) = split ':', $h->{$akey};
          my ($err)             = isDeviceValid ( { name => $name, obj => $dv, method => 'string' } );
          return $err if($err);

          my $val = ReadingsVal ($dv, $rd, undef);
         
          if (!defined $val) {
              return "The reading '$rd' of device '$dv' is invalid or doesn't contain a defined value";
          }
         
          if (defined $regex) {
              $err = checkRegex ($regex);
              return "$akey Regex check failed: $err" if($err);
          }
      }
  }
  elsif ($paref->{cmd} eq 'del') {

  }

  InternalTimer (gettimeofday() + 2, 'FHEM::SolarForecast::createAssociatedWith', $hash, 0);
  InternalTimer (gettimeofday() + 3, 'FHEM::SolarForecast::writeCacheToFile', [$name, 'plantconfig', $plantcfg.$name], 0);   # Anlagenkonfiguration File schreiben

return;
}

Parse

################################################################
#                Parse setupHPDev 300P
################################################################
sub __parseAttrHPDev { ##+
  my $name = shift;    ##+
  my $hpm = AttrVal ($name, 'setupHPDev', '');##+
  return if(!$hpm);##+
  my ($pa, $ph) = parseParams ($hpm);##+
  ##+
  my ($hpspfdev,           $hpspfrdg)           = split (':', $ph->{hpspf},             2) if(defined $ph->{hpspf});##+
  my ($hptempflowdev,      $hptempflowrdg)      = split (':', $ph->{hptempflow},        2) if(defined $ph->{hptempflow});##+
  my ($hptempreturndev,    $hptempreturnrdg)    = split (':', $ph->{hptempreturn},      2) if(defined $ph->{hptempreturn});##+
  my ($hpmodeheatdev,      $hpmodeheatrdg)      = split (':', $ph->{hpmodeheat},        2) if(defined $ph->{hpmodeheat}); ##+
  my ($hpmodehwaterdev,    $hpmodehwaterrdg)    = split (':', $ph->{hpmodehwater},      2) if(defined $ph->{hpmodehwater}); ##+
  my ($hpmodedefrostdev,   $hpmodedefrostrdg)   = split (':', $ph->{hpmodedefrost},     2) if(defined $ph->{hpmodedefrost}); ##+
  my ($hpmodeoffdev,       $hpmodeoffrdg)       = split (':', $ph->{hpmodeoff},         2) if(defined $ph->{hpmodeoff}); ##+
  my ($hpmodecooldev,      $hpmodecoolrdg)      = split (':', $ph->{hpmodecool},        2) if(defined $ph->{hpmodecool}); ##+
  my ($hpmodepooldev,      $hpmodepoolrdg)      = split (':', $ph->{hpmodepool},        2) if(defined $ph->{hpmodepool}); ##+
  my ($hpmodepoolheatdev,  $hpmodepoolheatrdg)  = split (':', $ph->{hpmodepoolheat},    2) if(defined $ph->{hpmodepoolheat}); ##+
  # Moeggliche wpmode-werte sind "off","heating","cooling","hot water","pool","pool heating","defrost","compressor alarm" not used   ##+
##+ Ein Modus Alarm wird in SF nicht bewertet
##+
  my $parsed = {    ##+
      hpspfDev           => $hpspfdev,           ##+
      hpspfRdg           => $hpspfrdg,           ##+
      hptempflowDev      => $hptempflowdev,      ##+
      hptempflowRdg      => $hptempflowrdg,      ##+
      hptempreturnDev    => $hptempreturndev,    ##+
      hptempreturnRdg    => $hptempreturnrdg,    ##+
      hpmodeheatDev      => $hpmodeheatdev,      ##+
      hpmodeheatRdg      => $hpmodeheatrdg,      ##+
      hpmodehwaterDev    => $hpmodehwaterdev,    ##+
      hpmodehwaterRdg    => $hpmodehwaterrdg,    ##+
      hpmodedefrostDev   => $hpmodedefrostdev,   ##+
      hpmodedefrostRdg   => $hpmodedefrostrdg,   ##+
      hpmodeoffDev       => $hpmodeoffdev,       ##+
      hpmodeoffRdg       => $hpmodeoffrdg,       ##+
      hpmodecoolDev      => $hpmodecooldev,      ##+
      hpmodecoolRdg      => $hpmodecoolrdg,      ##+
      hpmodepoolDev      => $hpmodepooldev,      ##+
      hpmodepoolRdg      => $hpmodepoolrdg,      ##+
      hpmodepoolheatDev  => $hpmodepoolheatdev,  ##+
      hpmodepoolheatRdg  => $hpmodepoolheatrdg,  ##+
   };

   ##+ Debuglog HPDev
   ################
   ##+ if ($debug =~ /aiProcess/xs) {
   #Log3 ($name, 2, "$name DEBUG> parseAttrHPDev hpmodeheat: $hpmodeheatdev - hpmodewater : $hpmodehwaterdev - hpmodedefrost : $hpmodedefrostdev -hpmodeoff : $hpmodeoffdev ");
   #Log3 ($name, 2, "$name DEBUG> parseAttrHPDev hpmodeheat: $hpmodeheatrdg - hpmodewater : $hpmodehwaterrdg - hpmodedefrost : $hpmodedefrostrdg -hpmodeoff : $hpmodeoffrdg ");
    ##+ }
return $parsed;
}

Hilfe Ergänzung EN
      <a id="SolarForecast-attr-setupHPDev"></a>
       <li><b>setupHPDev &lt;key=value&gt; &lt;key=value&gt; ... </b><br>
         By optionally specifying the 'key=value' pairs listed below, various
         heatpump data / sensor can be integrated.
         The entry can be made on multiple lines.
         <br><br>
         ##+ 300P
         <br><br>


       <br>            <tr><td> English missing !!!!!!!                             </td><td>                                                                                                                                                  </td></tr>
       </li>
       <br>


Hilfe Ergänzung DE

      <a id="SolarForecast-attr-setupHPDev"></a>
       <li><b>setupHPDev &lt;key=value&gt; &lt;key=value&gt; ... </b><br>
         Durch die optionale Angabe der nachfolgend aufgeführten 'Schlüssel=Wert' Paare können verschiedene
         WP-Messwerte und Zustaende eingebunden werden.
         Die Eingabe kann mehrzeilig erfolgen. Dieses Setuop wird aktuell nur bei Auswahl der AI:FANN mit der Version V1_heatpump_pv_buderus genutzt
         <br><br>

         <br><br>
         ##+ 300P
         <br><br>

         <ul>
         <table>
         <colgroup> <col width="15%"> <col width="77%"> </colgroup>
            <tr><td> <b>hpspf</b>                 </td><td>deutsche JAZ  = erzeugte Waermemenge / Energiegesamteinsatz -  keine Pflichtangabe          </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hptempflow</b>            </td><td>Vorlauftemperatur vom Aussengeraet   - nicht vom Heizkreis  - ca. 34.0 Grad    - keine Pflichtangabe            </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hptempreturn</b>          </td><td>Ruecklauftemperatur zum Aussengeraet - nicht vom Heizkreis  = hptempflow-(delta 4.5 K --> Differenz VL/RL) </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodeheat</b>            </td><td>WP laeuft im Heizmodus     - keine Pflichtangabe                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodehwater</b>          </td><td>WP laeuft im Heizmodus     - keine Pflichtangabe                                                         </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodedefrost</b>         </td><td>WP laeuft im Abtaumodus    - keine Pflichtangabe                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodeoff</b>             </td><td>WP ist AUS - OFF           - keine Pflichtangabe                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodecool</b>            </td><td>WP laeuft im Kuehlmodus    - keine Pflichtangabe                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodepool</b>            </td><td>WP laeuft im Poolmodus     - keine Pflichtangabe                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td> <b>hpmodepoolheat</b>        </td><td>WP laeuft im Poolheatmodus - keine Pflichtangabe                                                         </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td>                              </td><td>Eine &lt;Gerät&gt;:&lt;Reading&gt; Kombination, die die jeweiligen aktuellen Werte der Waermepumpe liefert.                           </td></tr>
            <tr><td>                              </td><td>Syntax: &lt;Device&gt;:&lt;Reading&gt;                                                                                                    </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td>                              </td><td>  noch nicht vorhanden......                                                                                                                                        </td></tr>
            <tr><td>                              </td><td>                                                                                                                                          </td></tr>
            <tr><td>                              </td><td>Eine &lt;Gerät&gt;:&lt;Reading&gt;:&lt;Regex&gt; Kombination, die den aktuellen Kompressormodus für "heating" liefert.                    </td></tr>
            <tr><td>                              </td><td>Der angegebene reguläre Ausdruck muß 'true' für den Status 'heating|cooling|hotwater|defrost|off|pool|poolheating' ergeben, sonst 'false'.</td></tr>
            <tr><td>                              </td><td>Syntax: &lt;Gerät&gt;:&lt;Reading&gt;:&lt;Regex&gt;                                                                                       </td></tr>
            <tr><td>                                                                                                                                                                                 </td></tr>
            <tr><td>                                                                                                                                                                                 </td></tr>
            <tr><td>                                                                                                                                                                                 </td></tr>
         </table>
         </ul>
       <ul>

         <b>Beispiel: </b> <br>
         attr &lt;name&gt; setupHPDev hpmodeheat=Forecast:user_hpmodeheating <br>
                                      hpmodehwater=Forecast:user_hpmodehwater <br>
                                      hpmodedefrost=Forecast:user_hpmodedefrost <br>
                                      hpmodeoff=Forecast:user_hpmodeoff <br>
        <br><br>
        Userreading als Beispiel: (Device/Reading anpassen)<br>

                    user_hpmodeheating {if(ReadingsVal("MQTT_EMSwp","boiler_data_hpactivity","") eq "heating") {return "1"} else {return 0}},
                    user_hpmodehwater {if(ReadingsVal("MQTT_EMSwp","boiler_data_hpactivity","") eq "hot water") {return "1"} else {return 0}},
                    user_hpmodeoff {if(ReadingsVal("MQTT_EMSwp","boiler_data_hpactivity","") eq "off") {return "1"} else {return 0}},
                    user_hpmodedefrost {if(ReadingsVal("MQTT_EMSwp","boiler_data_hpactivity","") eq "off") {return "1"} else {return 0}},
       </ul>

       </li>
       <br>
Gruß
300P

FHEM 6.4|RPi|SMAEM|SMAInverter|SolarForecast| DbLog|DbRep|MariaDB|Buderus-MQTT_EMS|
Fritzbox|fhempy|JsonMod|HTTPMOD|Modbus ser+TCP| ESP32_AI_on_the_Edge|ESP32CAM usw.

DS_Starter

Ich habe mir den Link des Requests in mein Backlog gelegt.
Komme sonst mit meinem Plan durcheinander. (Ist eine größere Sache)
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

300P

Ja glaub ich .... Danke für die Aufnahme des Request in den Backlog 8)
Gruß
300P

FHEM 6.4|RPi|SMAEM|SMAInverter|SolarForecast| DbLog|DbRep|MariaDB|Buderus-MQTT_EMS|
Fritzbox|fhempy|JsonMod|HTTPMOD|Modbus ser+TCP| ESP32_AI_on_the_Edge|ESP32CAM usw.

klaus.schauer

Ich nutze die Readings
Today_MaxPVforecast
Today_MaxPVforecastTime
um den optimalen Zeitpunkt für das starke Aufheizen des Warmwasserspeichers (Legionellen-Funktion) zu bestimmen. Die Funktion prüft stündlich auf Today_MaxPVforecastTime und schaltet bei ausreichendem PV-Überschuss in einem Zeitkorridor von 7 bis 14 Tagen einmalig ein.

Nun kann sich, wie ich heute festgestellt habe, die Uhrzeit in Today_MaxPVforecastTime im Tagesverlauf ändern. Wenn sich aber der in Today_MaxPVforecastTime hinterlegte Zeitpunkt z. B. um 12:00 von 14:00 nach 11:00 ändert und ich ab 13:00 prüfe, habe ich mit meiner derzeitigen Routine Pech.

Grundsätzlich ist diese Funktionalität richtig, wenn man zu jedem Zeitpunkt des laufenden Tages - auch rückwirkend - den tatsächlichen Zeitpunkt von Today_MaxPVforecast ausgeben will. Für meine Funktion ist das natürlich kontraproduktiv. Gibt es - abgesehen von dem formalen Aspekt - einen besonderen Grund für die auch rückwirkende Berechnung des Zeitpunktes?

300P

@DS_Starter


Normierungsgrenzen: PV=10450 Wh, Hausverbrauch: Min=0 Wh / Max=7598 Wh

Das sollte jetzt okay sein:
Sicherheitsfaktor = 10 %
9.500 Wh * 1.1 = 10.450 Wh
Gruß
300P

FHEM 6.4|RPi|SMAEM|SMAInverter|SolarForecast| DbLog|DbRep|MariaDB|Buderus-MQTT_EMS|
Fritzbox|fhempy|JsonMod|HTTPMOD|Modbus ser+TCP| ESP32_AI_on_the_Edge|ESP32CAM usw.

DS_Starter

#5408
ZitatGibt es - abgesehen von dem formalen Aspekt - einen besonderen Grund für die auch rückwirkende Berechnung des Zeitpunktes?
Das ist letztendlich eine Auswertung der Readings "Today_Hour..._PVforecast". Eine rückwirkende Änderung gibt es nur insofern wenn sich eine Erwartungshaltung einer höheren Ausbeute in der Zukunft negiert.

Beispiel:
- es ist 11:00 und zum jetzigen Zeitpunkt wird aktuell 1500 Wh und das Maximimum von 2000 Wh 14:00 erwartet.
- um 12:00 ist die Erwartung auch noch so, wegen Bewölkung in der aktuellen Stunde nur 1000 Wh erwartet
- um 13:00 meldet der Wetterdienst eine Änderung und um  14:00 nur noch 1200 Wh und später auch weniger

-> dann wird das Maximum "rückwirkend" über die Auswertung der Readings von 14:00 auf 12:00 korrigiert.

LG,
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

DS_Starter

Ich habe die Drift-Korrekturlogik weiter optimiert.

2026.03.15 20:00:04.944 1: SolCast DEBUG> DRIFT [con]: Flag=mild | Block=0 | SlopeLive=0.305 | DriftSlope=1.061 | BiasLive=462.46 | DriftBias=-39.54 | RMSErelLive=56.2 | RMSErelRatio=3.31 | BiasVarNorm=0.21 |DriftScore=2.32 | Zone3Hours=1 | Hist=[mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild,mild]

Die Logik sollte recht aktiv Rekalibrierungen vornehmen und nicht mehr so lange durchgehend blockieren (Block=xxxxx).

Update liegt als 2.4.0 im contrib.

LB,
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter