PV - neuen Zähler aus bestehendem Zähler erzeugen

Begonnen von Wolle02, 25 Juli 2025, 14:13:11

Vorheriges Thema - Nächstes Thema

Wolle02

Hallo zusammen, nachdem bei mir meine PV Anlage installiert wurde und auch in Fhem diesbezüglich alles toll läuft, will ich mich nun dem Thema "Einspeisevergütung" widmen. Neuerdings ist es ja so, dass man keine Einspeisevergütung für die Zeit mehr bekommt, bei der an der EEX negative Strompreise gehandelt werden. Um den Überblick über meine vergütungsfähige Einspeisung zu behalten will ich mir nun einen Zähler bauen, der nur die Einspeisung zählt, wenn positive Strompreise gehandelt werden.

Ich habe hier meinen normalen Hausstromzähler, den ich mit dem OBIS Modul auslese. Hier wird auch die Einspeisung erfasst.
Zusätzlich habe ich ein Device erstellt mit dem per JsonMod über Tibber die Strompreise des aktuellen Tages bezogen werden.

Mir fehlt nun leider völlig die Idee wie ich hieraus einen neuen Zähler erstelle, der nur die Stromeinspeisung zählt, wenn bei Tibber für die aktuelle Zeit der Einspeisung ein positiver Preis anliegt.

Einfach ein Userreading zu erstellen, das den Wert des bestehenden Stromzählers nur dann hochzählt, wenn ein positiver Preis anliegt, ist ja zu kurz gesprungen, weil das Hochzählen bei negativem Preis dann zwar aufhört, jedoch bei erneutem positiven Preis sofort wieder auf den gleichen Wert wie der Hauptzähler springt anstatt an der gleichen Stelle wo er aufgehört hat zu zählen weiter zu zählen. Ich hoffe ihr versteht was ich meine.  ;D

Hat hier jemand eventuell eine zündende Idee für mich wie man so was angehen könnte?

betateilchen

Ich glaube, Du denkst zu kompliziert.
Was ist die tatsächliche Aufgabe?
  • Merke Dir beim Wechsel von negativem zu positivem Strompreis den Zählerstand
  • Merke Dir beim nächsten Wechsel von positivem zu negativem Strompreis den Zählerstand
  • Berechne aus 2-1 die letzte Einspeisungsmenge und addiere diese zur vorher gemerkten Einspeisemenge (aus dem letzten Zyklus)
  • Wiederhole das Ganze ab 1

Aber ich vermute, dass es für sowas sogar schon längst was "Fertiges" in FHEM gibt, Du bist ja nicht der Erste, der vor dieser Aufgabe steht.
Wenn ich nach "Einspeisevergütung" suche, kommen einige Ergebnisse.

Warum stellst Du diese Frage in den Anfängerfragen, anstatt im dafür vorgesehenen Unterforum?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Wolle02

ZitatMerke Dir beim Wechsel von negativem zu positivem Strompreis den Zählerstand
Merke Dir beim nächsten Wechsel von positivem zu negativem Strompreis den Zählerstand
Berechne aus 2-1 die letzte Einspeisungsmenge und addiere diese zur vorher gemerkten Einspeisemenge (aus dem letzten Zyklus)
Wiederhole das Ganze ab 1

Vielen Dank für die Anregung. Da muss ich jetzt erstmal ein wenig drauf rumdenken bis ich verstehe wie du das meinst und wie ich das umsetzen könnte.  ;D

ZitatAber ich vermute, dass es für sowas sogar schon längst was "Fertiges" in FHEM gibt, Du bist ja nicht der Erste, der vor dieser Aufgabe steht.
Wenn ich nach "Einspeisevergütung" suche, kommen einige Ergebnisse.

Das wäre natürlich toll, wenn es da was fertiges gäbe; bin da aber etwas Lost. Kennst du ein Modul, das solche Hilfsberechnungen anstellt?
Ich habe auch mal nach "Einspeisevergütung" gesucht, aber die Ergebnisse beziehen sich nicht auf das gestellte Problem. Den Usecase gibt es ja auch erst seit diesem Jahr (jedenfalls für dieses spezielle Szenario).

ZitatWarum stellst Du diese Frage in den Anfängerfragen, anstatt im dafür vorgesehenen Unterforum?

Naja, welches vorgesehene Unterforum wäre das denn? Solar? Energiemanagemet?
Vom Kontext her würde das zwar passen, aber vom Grundsatz her geht es bei meiner Frage ja nicht um eine PV Anlage oder um Energiemanagement, sondern eher um eine Programmierfrage. Und da ist mir halt kein anderes Unterforum eingefallen. Sorry.

betateilchen

#3
Zitat von: Wolle02 am 25 Juli 2025, 15:09:54aber vom Grundsatz her geht es bei meiner Frage ja nicht um eine PV Anlage oder um Energiemanagement, sondern eher um eine Programmierfrage.

Nein, es geht darum, eine Aufgabe möglichst einfach zu beschreiben. Das hat noch lange nichts mit "Programmierfrage" zu tun.
Letztendlich geht es um "Einspeisevergütung" aus einer PV Anlage. Da bietet sich entweder das Unterforum "Solaranlagen" oder das Unterforum "Verbrauchsmessung" an.

Man muss nun wirklich nicht mit allem die "Anfängerfragen" zumüllen.
Zumal der Bereich "Anfängerfragen" auch für tatsächliche Programmierfragen falsch wäre.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

ch.eick

Hallo zusammen,
für Tibber gibt es ja bereits ein EVU_Tibber_connect Device, das als Basis dienen könnte.
Hier gibt es einen Thread zu Tibber.

Wenn Du jedoch kein Tibber hast, ist das eigentlich der falsche Ansatz, denn Du bräuchtest ja den EEX Preis. Bei Tibber sind ja noch viele andere Teile im Preis mit verrechnet, sodass man dort eventuell zu anderen Zeiten auf negative Preise kommen würde.

Ich würde das, wie bereits hier vorgeschlagen auch bei Solaranlagen sehen.
Bitte geh dazu in den ersten Post und verschiebe es.

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

Wolle02

Für den Fall, dass jemand den gleichen Usecase hat und nach einer Lösung sucht. Ich verwende aktuell folgenden Code in einer 99_myUtils.

###########################################################
#Routine zur Verwendung eines Dummy-Devices als Einspeisezähler, der nur die Stromeinspeisung während positiver Strompreise an der Strombörse (EEX) zählt.
#Das Dummy Device kann folgendermaßen definiert werden:
#
#defmod Stromzaehler_Einspeisung_Positiv dummy
#attr Stromzaehler_Einspeisung_Positiv readingList lastPositivePeriodFeed previousPositivePeriodFeed FeedAtPriceChange priceWasPositive
#attr Stromzaehler_Einspeisung_Positiv setList lastPositivePeriodFeed previousPositivePeriodFeed FeedAtPriceChange priceWasPositive
#attr Stromzaehler_Einspeisung_Positiv stateFormat {sprintf("%.4f kWh", ReadingsVal($name,"state",0)/1000)}
#
#Die Strompreise werden durch ein Tibber-Device bezogen, welches separat erstellt werden muss und den aktuellen Strompreis im Reading "Preis" bereitstellt.
#
#

package main;

use strict;
use warnings;

sub calculatePositivePriceFeed() {
    my $einspeiseZaehler = "Hausstromzaehler"; # Name des originalen Einspeisezählers
    my $tibberDevice = "Tibber";               # Name des Tibber-Devices
    my $targetCounter = "Stromzaehler_Einspeisung_Positiv"; # Name des Dummy Devices (des neuen Zählers)

    # Aktuellen Tibber-Preis abrufen
    my $currentPrice = ReadingsVal($tibberDevice, "Preis", 9999); # Standardwert hoch, falls nicht verfügbar

    # Aktuellen Zählerstand des Einspeisezählers abrufen
    my $currentFeed = ReadingsVal($einspeiseZaehler, "overall_feed", 0);

    # Status des neuen Zählers abrufen (speichert ob der Preis zuletzt positiv war)
    my $isPricePositiveLastTime = ReadingsVal($targetCounter, "priceWasPositive", 0); # 0=negativ/unbekannt, 1=positiv

    # vorherige Einspeisung von positiver Periode
    my $previousPositivePeriodFeed = ReadingsVal($targetCounter, "previousPositivePeriodFeed", 0);

    # Zählerstand beim letzten Preiswechsel
    my $FeedAtPriceChange = ReadingsVal($targetCounter, "FeedAtPriceChange", $currentFeed);


    Log 3, "calculatePositivePriceFeed: Tibber Preis: $currentPrice";

    # Preiswechsel von negativ zu positiv
    if ($currentPrice >= 0 && !$isPricePositiveLastTime) {
        Log 3, "calculatePositivePriceFeed: Preiswechsel von negativ zu positiv. Speichere aktuellen Zählerstand.";
        fhem("setreading $targetCounter FeedAtPriceChange $currentFeed");
        fhem("setreading $targetCounter priceWasPositive 1"); # Preis ist jetzt positiv
    }
    # Preiswechsel von positiv zu negativ
    elsif ($currentPrice < 0 && $isPricePositiveLastTime) {
        Log 3, "calculatePositivePriceFeed: Preiswechsel von positiv zu negativ. Berechne Einspeisung der letzten Periode.";

        # Aktuellen Zählerstand erfassen
        my $FeedAtNegativeChange = $currentFeed;

        # Berechnung der Einspeisung der letzten positiven Periode
        my $lastPositivePeriodFeed = $FeedAtNegativeChange - $FeedAtPriceChange;

        # Sicherstellen, dass die Einspeisung nicht negativ wird (z.B. bei Zählerrücksetzung oder Fehlern)
        $lastPositivePeriodFeed = ($lastPositivePeriodFeed > 0) ? $lastPositivePeriodFeed : 0;

        Log 3, "calculatePositivePriceFeed: Einspeisung der letzten Positivperiode: $lastPositivePeriodFeed Wh, Zählerstand am Ende der letzten Positivperiode: $previousPositivePeriodFeed";

        # Addiere zur bisherigen Gesamtmenge
        $previousPositivePeriodFeed += $lastPositivePeriodFeed;

        # Setze Readings im Dummy-Device
        fhem("setreading $targetCounter lastPositivePeriodFeed $lastPositivePeriodFeed");
        fhem("setreading $targetCounter previousPositivePeriodFeed $previousPositivePeriodFeed");
        fhem("setreading $targetCounter state $previousPositivePeriodFeed"); # Das ist unser kumulierter Zählerstand
        fhem("setreading $targetCounter priceWasPositive 0"); # Preis ist jetzt negativ

        # Setze FeedAtPriceChange für den nächsten Zyklus
        fhem("setreading $targetCounter FeedAtPriceChange $currentFeed");
    }
    # Wenn der Preisstatus gleich bleibt
    elsif ($currentPrice < 0 && !$isPricePositiveLastTime) {
        Log 3, "calculatePositivePriceFeed: Preis bleibt negativ. Keine Aktion für Zählerupdate durchgeführt.";
    }
    elsif ($currentPrice >= 0 && $isPricePositiveLastTime) {
        Log 3, "calculatePositivePriceFeed: Preis bleibt positiv. Berechne Zählerstand der letzten Periode.";

# Aktuellen Zählerstand erfassen
        my $FeedAtCurrentRun = $currentFeed;

        # Berechnung der Einspeisung der letzten positiven Periode
        my $lastPositivePeriodFeed = $FeedAtCurrentRun - $FeedAtPriceChange;

        # Sicherstellen, dass die Einspeisung nicht negativ wird (z.B. bei Zählerrücksetzung oder Fehlern)
        $lastPositivePeriodFeed = ($lastPositivePeriodFeed > 0) ? $lastPositivePeriodFeed : 0;

        Log 3, "calculatePositivePriceFeed: Einspeisung der letzten Positivperiode: $lastPositivePeriodFeed Wh, Zählerstand am Ende der letzten Positivperiode: $previousPositivePeriodFeed";

        # Addiere zur bisherigen Gesamtmenge
        $previousPositivePeriodFeed += $lastPositivePeriodFeed;

        # Setze Readings im Dummy-Device
        fhem("setreading $targetCounter lastPositivePeriodFeed $lastPositivePeriodFeed");
        fhem("setreading $targetCounter previousPositivePeriodFeed $previousPositivePeriodFeed");
        fhem("setreading $targetCounter state $previousPositivePeriodFeed"); # Das ist unser kumulierter Zählerstand

        # Setze FeedAtPriceChange für den nächsten Zyklus
        fhem("setreading $targetCounter FeedAtPriceChange $currentFeed");
    }
}
1;

Im state des Dummys steht dann der Zählerstand, der nur bei positivem Strompreis hochzählt.