Hauptmenü

Neueste Beiträge

#11
Solaranlagen / Aw: 76_SolarForecast - Informa...
Letzter Beitrag von DS_Starter - 04 Januar 2026, 19:16:22
Hallo Klaus,

nein, einfach ist das Ganze mit Sicherheit nicht.

Deine Routinen könnten ein Baustein in der klassischen Prognose des Hausverbrauches sein. Denn das neuronale Netz betrachtet den den gesamten E-Verbauch des Haus in Abhängigkeit von verschiedenen Randbedingunge. Die WP ist nur ein Bestandteil davon. Deswegen nicht allzusehr nur auf WP fokussieren.

Die Variante mit einer ctrlUserExitFn ähnlichen Schnittstelle ist m.M. nach am ehesten sinnvoll, sonst müsste ich im WP Consumerstammsatz alle benötigten Parameter zwingend angeben lassen.
Dieser Userfunktion würde übergeben werden:

- Stunde / Timestamp für den der E-Bedarf der WP benötigt wird
- die Temp Prognose für diesen Timstamp
- die Windprognose für diesen Timestamp

Als Antwort würde erwartet:

- der Energiebedarf als Prognose für den Timestamp als Stundenwert, d.h. in Wh


Das Ganze natürlich optional, denn nicht jeder User wird in der Lage sein dies umzusetzen.

LG,
Heiko

#12
Homematic / Aw: HmIP-RGBW nicht über HMCCU...
Letzter Beitrag von Custodis Intestina - 04 Januar 2026, 19:15:16
Hallo ihr Lieben.
Hab voriges Jahr mal auf die HMip-RGBW umgestellt. Heute mal begonnen in einem neuen Fhem auf die Controller zuzugreifen. Giebt es da schon Neuerungen zwecks der HMCCU config?
Wenn ich das Device anlege habe ich 4 neue Channels logischer weiße kann ich nur den ersten richtig bedienen (RGBW eingestellt).
Hab auch mal die attr so wie oben eingerichtet. Aber das Saturation funktioniert da auch nicht.
Wollte nur mal Fragen ob es da schon eine Lösung gibt.

LG Steve
#13
Solaranlagen / Aw: 76_SolarForecast - Informa...
Letzter Beitrag von grappa24 - 04 Januar 2026, 19:09:13
mal ein Beispiel mit PHEV Laden  ;)
#14
Sonstiges / VERSCHOBEN: EVSE Wifi Wallbox
Letzter Beitrag von Otto123 - 04 Januar 2026, 18:59:39
#15
Heizungssteuerung/Raumklima / Aw: THZ Tecalor (LWZ Stiebel E...
Letzter Beitrag von willybauss - 04 Januar 2026, 18:20:34
Zitat von: dvdjimmy am 04 Januar 2026, 17:01:32Bzgl. Abtauvorgang kann man vermutlich nicht viel einstellen, oder?
Nö, wie auch? Du müsstest "irgendwie" das Vereisen verhindern, z.B. die angesaugte Luft trocknen ...
#16
Solaranlagen / Aw: 76_SolarForecast - Informa...
Letzter Beitrag von klaus.schauer - 04 Januar 2026, 18:14:39
Zitat von: DS_Starter am 04 Januar 2026, 14:56:14Ein interessanter Artikel zum Thema WP und Energievorhersage und ziemlich vollständig das beschreibt was auch im SF umgesetzt ist:
https://medium.com/@omegaxp3/predicting-future-energy-consumption-using-neural-network-based-on-historical-data-and-temperature-819028398301
Interessant an den Ergebnissen ist, dass die Vorhersagen bei nicht monotonem Verhalten stark fehlerbehaftet waren. Und dabei hat man sich ausschließlich auf eine Korrelation zwischen Energieverbrauch, Außentemperatur und die zeitliche Abhängigkeit konzentriert.

In dein geplantes KI-Model sollen viele weitere Randbedingungen einfließen. Auch soll wohl der Energieverbrauch als Ganzes betrachtet werden. Das macht die Sache sicherlich nicht einfacher und bestärkt mich in meiner Skepsis. Konkret bringt uns deshalb das Training mit mehr oder weniger beziehungslosen historischen Energiedaten oder auch der Wunsch nach einer noch unbekannten Standardkenngröße von Wärmepumpen für den aktuellen Energieverbrauch nicht weiter.

Unabhängig von der Art des Wärmeerzeugers benötigt ein Gebäude eine bestimmte Heizleistung, um eine gewünschte Innentemperatur zu gewährleisten. Deshalb wäre m. E. sinnvoll, dies als Führungsgröße bereitzustellen, die deterministisch berechnet wird.

Für die Energiebedarfsprognose einer Wärmepumpe reichen wenige deterministische Daten. Vom Gebäude sollten der Verlustkoeffizient H [W/K] aus Heizlastberechnung (DIN EN 12831), die Wärmekapazität des Gebäudes C [Wh/K] und COP-Wert der Wärmepumpe bekannt sein oder abgeschätzt werden. Als Wetterdaten werden die Prognosen für Außentemperatur und die Windgeschwindigkeit benötigt. Die Sollinnentemperatur kann über die hinterlegten Zeitfenster der Heizung abgebildet werden.  Aus diesen Daten lässt sich die benötigte Eingangsleistung und der Energiebedarf z. B. in Stundenintervallen abschätzen. Über die Wärmekapazität C und die Windgeschwindigkeit kann zusätzlicher dynamischer Energiebedarf beim Aufheizen und durch Infiltrationswärmeverluste berücksichtigt werden.

Wie dies konkret berechnet wird, kann man der Routine myUtils_heatingEnergyDemand entnehmen, siehe unten. Die spezifischen Gebäudedaten und die COP-Werte der Wärmepumpe sind natürlich passend zu ermitteln. Die Berechnung kann natürlich das Nutzerverhalten oder auch Systemspezifika des Wärmeerzeugers wie Taktung, die Größe von Pufferspeichern oder Unterbrechungen durch Warmwasserbereitung nicht abbilden. Da wäre dann die KI gefragt.

Wenn man eine solche Berechnung nicht in SolarForecast einbauen wollte, könnte man mit einer Benutzerfunktion ähnlich wie bei ctrlUserExitFn Leistung oder Energie / h und die Sollinnentemperatur abrufen:
sub myUtils_heatingEnergyDemand {
  my ($hash, $name, $consumerNum, $timeOffset) = @_;

...

return ($energy, $setpointTemp);
}
Aktuell berechne ich die Energie / h mit nachfolgender Routine und schreibe den aktuellen Wert und die Prognosen in zusätzliche SolarForecast Readings. Die Funktion myUtils_heatingEnergyDemand wird in der ctrlUserExitFn zusammen mit anderen Hilfsfunktionen  aufgerufen und stündlich ausgeführt:
sub myUtils_ctrlUserExitFn {
  my ($hash, $name, $wrName, $hpName) = @_;

  myUtils_buildGridTariffArray($hash, $name);
  myUtils_buildSpotTariffHash($hash, $name);
  myUtils_consumerEnergyLastHour($hash, $name,'01'); 

  my ($sec, $min, $hour) = localtime;
  # Berechne den aktuellen 15-Minuten-Intervall-Start (z.B. 08:15, 08:30, ...)
  my $intervalMin = int($min / 15) * 15;
  my $intervalTag = sprintf("%02d:%02d", $hour, $intervalMin);
 
  # Ausfuehrung jeweils einmal zu Beginn eines 15 min Intervalls
  if (!exists($hash->{helper}{ctrlUserExitFn}{lastInterval}) || $hash->{helper}{ctrlUserExitFn}{lastInterval} ne $intervalTag) {
    $hash->{helper}{ctrlUserExitFn}{lastInterval} = $intervalTag;
    readingsBeginUpdate($hash);
    readingsBulkUpdateIfChanged($hash, 'gridTariff', myUtils_getCurrentGridTariff($hash, $name, sprintf("%02d:%02d", $hour, $min)), 1);
    readingsBulkUpdateIfChanged($hash, 'gridEnergyFixedPrice', myUtils_getCurrentTotalEnergyCosts($hash, $name, sprintf("%02d:%02d", $hour, $min)), 1);
    readingsBulkUpdateIfChanged($hash, 'gridEnergySpotPrice', myUtils_GetCurrentSpotEnergyCosts($hash, $name, sprintf("%02d:%02d", $hour, $min)), 1);
    readingsEndUpdate($hash, 1);
    myUtils_pvBatChargeRequest($hash, $name, $wrName);
    myUtils_heatingEnergyDemand($hash, $name, '01');
    myUtils_HPHcCharge($hash, $name, $hpName, $intervalTag);
    myUtils_HPHwcCharge($hash, $name, $hpName, $intervalTag);
  }

  return;
}
Die Funktion  myUtils_heatingEnergyDemand holt sich u. a. die Sollinnentemperatur unmittelbar aus der Wärmepumpe. Die Windgeschwindigkeit aus dem Modul DWD_OpenData.

Falls man den Weg über die vorgeschlagene Benutzerfunktion gehen würde, wäre die Funktion problemlos anpassbar. Festzulegen wäre dann noch,
   - ob der Berechnungszeitpunkt mit Datum und Uhrzeit oder als Zeitoffset übergeben wird und
   - ob die Eingangsleistung oder die Energie / t zurückgegeben werden soll.

Gut wäre auch, wenn SolarForecast neben den Temperaturdaten auch die Windgeschwindigkeit bereitstellen würde.     
# Schaetzung des Energiebedarfs faer Heizung abhaengig vom Verlustkoeffizient aus Heizlastberechnung (DIN EN 12831) und der Aussentemperatur
sub myUtils_heatingEnergyDemand {
  my ($hash, $name, $consumerNum) = @_;

  # Initialisiere Helper-Struktur bei Bedarf
  $hash->{helper}{ctrlUserExitFn} //= {};

  # Zeitabfrage
  my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
  my $nowEpoch = time;
  my $lastRunHour = $hash->{helper}{ctrlUserExitFn}{lastRunHour} // -1;
  return undef if ($lastRunHour == $hour);

  # Konstanten
  my $copMax = 5;
  my $copMin = 2.5;
  my $correctionFactor = 0.8;
  my $energyDiffMax = 0.3; # max. dynamischer Energieaufschlag
  my $energyHwcHour = 0; # Energiebedarf / h fuer Warmwasser
  my $heatCapacity = 16; # Waermekapazität des Gebaeudes C [Wh/K]
  my $heatingOutdoorDesignTemp = -8.5; # Auslegungstemperatur
  my $heatingLimitTemp = ReadingsVal('Heizung_ctlv3', 'ctlv3_Hc1SummerTempLimit', 16);
  my $helperKey = 'consumer' . $consumerNum;
  my $lossCoeff = 300; # Verlustkoeffizient H [W/K] aus Heizlastberechnung (DIN EN 12831)
  my $setpointSlotTemp = 20;
  my $setpointBackTemp = ReadingsVal('Heizung_ctlv3', 'ctlv3_z1SetBackTemp', 10);
  my $quickVetoTemp = ReadingsVal('Heizung_ctlv3', 'ctlv3_z1QuickVetoTemp', 20);
  my $periodSlotTemp = "04:30-21:00";
  my $z1Status = ReadingsVal('Heizung_ctlv3', 'ctlv3_z1Status', 'auto');

  # Endzeitpunkte parsen
  my ($holidayEndDay, $holidayEndMonth, $holidayEndYear) = split(/\./, ReadingsVal('Heizung_ctlv3', 'ctlv3_z1HolidayEndDate', '01.01.2000'));
  my ($holidayEndHour, $holidayEndMin, $holidayEndSec)   = split(/:/, ReadingsVal('Heizung_ctlv3', 'ctlv3_z1HolidayEndTime', '00:00:00'));
  my ($quickVetoEndDay, $quickVetoEndMonth, $quickVetoEndYear) = split(/\./, ReadingsVal('Heizung_ctlv3', 'ctlv3_z1QuickVetoEndDate', '01.01.2000'));
  my ($quickVetoEndHour, $quickVetoEndMin, $quickVetoEndSec)   = split(/:/, ReadingsVal('Heizung_ctlv3', 'ctlv3_z1QuickVetoEndTime', '00:00:00'));

  my $holidayEpoch    = timelocal($holidayEndSec, $holidayEndMin, $holidayEndHour, $holidayEndDay, $holidayEndMonth - 1, $holidayEndYear);
  my $quickVetoEpoch  = timelocal($quickVetoEndSec, $quickVetoEndMin, $quickVetoEndHour, $quickVetoEndDay, $quickVetoEndMonth - 1, $quickVetoEndYear);

  # Slot-Zeitraum parsen
  my ($startSlot, $endSlot) = split /-/, $periodSlotTemp;
  my ($startHour, $startMin) = split /:/, $startSlot;
  my ($endHour, $endMin) = split /:/, $endSlot;

  # Hilfsfunktion: Slot-Temperatur
  sub getSetpointTempForHour {
    my ($h, $startHour, $startMin, $endHour, $endMin, $slotTemp, $backTemp) = @_;
    return $slotTemp if (
      ($h > $startHour && $h < $endHour) or
      ($h == $startHour && $startMin == 0) or
      ($h == $endHour && $endMin > 0)
    );
    return $backTemp;
  }

  # Hilfsfunktion: Sonderstatus prüfen
  sub overrideSetpointIfActive {
    my ($status, $epochNow, $holidayEpoch, $quickVetoEpoch, $backTemp, $vetoTemp) = @_;
    return $backTemp if ($status eq 'holiday_away' && $epochNow < $holidayEpoch);
    return $vetoTemp if ($status eq 'quick_veto'   && $epochNow < $quickVetoEpoch);
    return undef;
  }

  # Energiebedarf / h (statisch / dynamisch)
  sub heatingCalcDynamic {
    my ($lossCoeff, $copMax, $copMin, $correctionFactor, $heatCapacity, $energyDiffMax, $energyHwcHour, $setpointTemp, $setpointTempLast, $tempOutside, $heatingOutdoorDesignTemp, $heatingLimitTemp, $wind) = @_;
    return (0, 0, 0) if ($tempOutside >= $setpointTemp || $tempOutside >= $heatingLimitTemp);

    # COP Wert in Abhaengigkeit der Aussentemperatut (lineare Interpolation)
    my $cop = $copMin + ($copMax - $copMin) * (($tempOutside - $heatingOutdoorDesignTemp) / ($heatingLimitTemp - $heatingOutdoorDesignTemp));
    # Falls unterhalb der Auslegungstemperatur, COP bleibt minimal
    $cop = $copMin if ($tempOutside <= $heatingOutdoorDesignTemp);
    # Falls oberhalb der maximalen Temperatur, COP bleibt maximal
    $cop = $copMax if ($tempOutside >= $heatingLimitTemp);

    # Basislast: Verlustkoeffizient * Temperaturdifferenz
    my $energyBase = $lossCoeff / $cop * $correctionFactor * ($setpointTemp - $tempOutside);

    # Windkorrekturfaktor (Annahme: ab 20 km/h Wind steigt Infiltration linear um bis zu +20 %)
    my $windFactor = 1.0;
    if (defined $wind && $wind > 20) {
        # Skaliere zwischen 20 km/h und 60 km/h
        my $windGradient = ($wind - 20) / 40; # 0 bis 1
        $windGradient = 1 if $windGradient > 1; # Deckelung
        $windFactor += 0.2 * $windGradient; # max. +20 %
    }
    $energyBase *= $windFactor;

    # Änderung der Solltemperatur pro Stunde
    my $deltaTsoll = $setpointTemp - $setpointTempLast;

    # Dynamische Zusatzlast: Gebaeudekapazität * Temperaturänderung / 1h
    # (1h = 3600s, hier vereinfachend pro Stunde gerechnet)
    my $energyDyn = $heatCapacity * $deltaTsoll;

    # Begrenzung der Zusatzlast auf Prozentsatz der Basislast
    my $energyDynMax = $energyBase * $energyDiffMax;
    $energyDyn = $energyDynMax if $energyDyn > $energyDynMax;
    $energyDyn = 0 if $energyDyn < 0;   # keine negative Zusatzlast

    # Gesamtenergie inkl Energie fuer Warmwasser / h
    $energyBase += $energyHwcHour;
    my $energyTotal = $energyBase + $energyDyn;

    return ($energyBase, $energyDyn, $energyTotal, $cop);
  }

  sub toDayHour {
    my ($value) = @_;
    # Ganze Tage = Division durch 24
    my $day  = int($value / 24);
    # Reststunden = Modulo 24
    my $hour = $value % 24;
   return ($day, $hour);
  }

  readingsBeginUpdate($hash);

  # Aktuelle Stunde
  my $setpointTemp = overrideSetpointIfActive($z1Status, $nowEpoch, $holidayEpoch, $quickVetoEpoch, $setpointBackTemp, $quickVetoTemp);
  $setpointTemp //= getSetpointTempForHour($hour, $startHour, $startMin, $endHour, $endMin, $setpointSlotTemp, $setpointBackTemp);
  my $setpointTempLast = $hash->{helper}{$helperKey}{setpointTemp}{current} // $setpointTemp;
  my $tempHour = FHEM::SolarForecast::CurrentVal($name, 'temp', $heatingLimitTemp);
  my ($energyBase, $energyDyn, $energyTotal, $cop) = heatingCalcDynamic ($lossCoeff, $copMax, $copMin, $correctionFactor, $heatCapacity, $energyDiffMax,
                                                                   $energyHwcHour,
                                                                   $setpointTemp, $setpointTempLast,
                                                                   $tempHour, $heatingOutdoorDesignTemp, $heatingLimitTemp,
                                                                   ReadingsVal("Wetter_DWD", "fc0_" . $hour . "_FF", 0));
  $hash->{helper}{$helperKey}{setpointTemp}{current} = $setpointTemp;
  readingsBulkUpdateIfChanged($hash, 'consumer' . $consumerNum . '_consumptionCalc_Current', int($energyBase) . " Wh", 1);
  readingsBulkUpdateIfChanged($hash, 'consumer' . $consumerNum . '_consumptionCalcDyn_Current', int($energyTotal) . " Wh", 1);
  readingsBulkUpdateIfChanged($hash, 'consumer' . $consumerNum . '_copCalc_Current', sprintf('%0.1f', $cop), 1);

  # Folge-Stunden
  for my $indexHour (0 .. 23) {
    my $futureEpoch = $nowEpoch + ($indexHour + 1) * 3600;
    my ($futureDay, $futureHour) = toDayHour ($hour + $indexHour + 1);
    $setpointTemp = overrideSetpointIfActive($z1Status, $futureEpoch, $holidayEpoch, $quickVetoEpoch, $setpointBackTemp, $quickVetoTemp);
    $setpointTemp //= getSetpointTempForHour($futureHour, $startHour, $startMin, $endHour, $endMin, $setpointSlotTemp, $setpointBackTemp);
    $hash->{helper}{$helperKey}{setpointTemp}{$indexHour} = $setpointTemp;
    $setpointTempLast = $indexHour == 0 ? $hash->{helper}{$helperKey}{setpointTemp}{current} // $setpointTemp : $hash->{helper}{$helperKey}{setpointTemp}{$indexHour - 1} // $setpointTemp;
    $tempHour = FHEM::SolarForecast::NexthoursVal($name, 'NextHour' . sprintf('%02d', $indexHour), 'temp', $heatingLimitTemp);
    ($energyBase, $energyDyn, $energyTotal, $cop) = heatingCalcDynamic ($lossCoeff, $copMax, $copMin, $correctionFactor, $heatCapacity, $energyDiffMax,
                                                                  $energyHwcHour,
                                                                  $setpointTemp, $setpointTempLast,
                                                                  $tempHour, $heatingOutdoorDesignTemp, $heatingLimitTemp,
                                                                  ReadingsVal("Wetter_DWD", "fc" . $futureDay . "_" . $futureHour . "_FF", 0));
    readingsBulkUpdateIfChanged($hash, 'consumer' . $consumerNum . '_consumptionCalc_NextHour' . sprintf('%02d', $indexHour), int($energyBase) . " Wh", 1);
    readingsBulkUpdateIfChanged($hash, 'consumer' . $consumerNum . '_consumptionCalcDyn_NextHour' . sprintf('%02d', $indexHour), int($energyTotal) . " Wh", 1);
  }

  readingsEndUpdate($hash, 1);

  # Merke letzte Ausführungsstunde
  $hash->{helper}{ctrlUserExitFn}{lastRunHour} = $hour;

  return undef;
}
#17
Solaranlagen / Aw: 76_SolarForecast - Informa...
Letzter Beitrag von 300P - 04 Januar 2026, 17:55:18
Kurzanleitung:

Meist schreibe ich mir am Anfang von neuen Sachen alle Parameter mit default-Wert - egal ob ich Standart nutze oder nicht -  zur Übersicht mit in die jeweiligen Attribute hinein um dann den einen deren evtl. mal dann auszuprobieren.
=>> Aber das ist Ansichtssache

Zu Anfang aber mind. eintragen (m.W.n.)
!!hinzufügen !!
attr >Forecast< ctrlDebug aiProcess
!!hinzufügen !!
attr <Forecast> aiConActivate=1

Dann zum ersten Start des Trainings mittels
set Forecast aiDecTree runConTrain.....und das Logbuch beobachten....
Kann bis zu  2-4 Stunden dann dauern ehe dieser Lauf beendet ist.

Dann optimieren durch "Feintuning" und diverse Einstellungen............ ;D

Der Rest nach dem WIKI bzw. Infos aus dem Thread ;)
#18
Server - Windows / fhem, direkt unter windows mit...
Letzter Beitrag von the ratman - 04 Januar 2026, 17:48:58
auf der suche nach dem einfachsten weg, fhem unter windows zum sprechen zu bringen ... eine lösung

info:
1) ich danke hier "noob_at_pc" und "˗ˋˏAd0larˎˊ˗" aus dem kodinerds-matrix-chat für ihre geduldige hilfe!
2) da ich fhem unter c:/fhem/ installiert habe, bitte die pfade beachten!

o) nach der offiziellen anleitung von hier https://wiki.fhem.de/wiki/FHEM_Installation_Windows fhem auf windows installieren.
o) die neueste powershell installiert? windows meckert ansonsten.
hier gibt's infos: https://learn.microsoft.com/de-de/powershell/scripting/install/install-powershell-on-windows?view=powershell-7.5
die installation aber unbedingt über den installer vornehmen, NICHT über den microsoft-store. ansonsten gibts probleme mit den pfaden.
o) set-executionpolicy remotesigned einmalig als administrator in der powershell ausführen.

o) in c:/fhem/ folgende 3 zeilenAdd-Type -AssemblyName System.Speech
$synth = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$synth.Speak($args[0])
als tts.ps1 speichern

o) ein cmdalias in fhem anlegendefmod say cmdalias say .* AS {system('cmd', '/c','start','/B','""','c:\Program Files\PowerShell\7\pwsh.exe','-ExecutionPolicy','Bypass','c:\fhem\tts.ps1',$EVENT);;;;return''}
dies sollte blockingfrei und ohne zusätzliche ausgabe in fhem die win tts mit z.b.say mein text ist sehr einfallsreichzur sprachausgabe bewegen.

falls sich noch wer direkt unter win mit fhem spielt - ich habe keinerlei einwände, tipps und tricks zu bekommen *g*.
#19
FHEM Development / Aw: glob/Wildcards in CommandI...
Letzter Beitrag von jw2013 - 04 Januar 2026, 17:29:25
Besten Dank, und ein frohes Neues!

Ein Problem sehe ich: Bei der jetzigen Änderung würde beim nächsten "save" das glob include verloren gehen, und durch explizite include Anweisungen für einzelne Dateien ersetzt.

Ich hatte meinen Patch so angelegt, dass sich das Verhalten bezüglich $comments{$nr}{TEXT} nicht ändert, und das Kommando nicht rekursiv durchlaufen wird (was wieder explizite include Anweisungen erzeugt hätte).
#20
Multimedia / Aw: [Neues Modul] BOSE SoundTo...
Letzter Beitrag von betateilchen - 04 Januar 2026, 17:18:27
Du hast mich aber auf die Idee gebracht, die einzige Textkonserve, die ich brauche, durch einen der online verfügbaren text-to-speech Konverter als mp3 erzeugen zu lassen.

Da die ST-Boxen inzwischen ja ohnehin die Fritzbox als Mediaserver nutzen, muss ich jetzt nur noch rausfinden, wo ich die mp3 korrekt ablegen muss.



Edit: Ablageort ist gefunden, Abspielen funktioniert einwandfrei.

Jetzt baue ich noch das "Drumrum", also die Zustandsspeicherung und -wiederherstellung, falls die Box schon lief.