Ankündigung

Einklappen
Keine Ankündigung bisher.

Item mit Zeitberechnung bspw für Verbrauchsauswertung als Systemitems bereitstellen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Sisamiwe
    antwortet
    Onkelandy

    Ich habe das gist nochmal aktualisiert und meine letzte Logik Version dort abgelegt.

    Leider ist die Performance der Logik deutlich schlechter also bei einer Abbildung über eval. Die Logik zum Aktualisieren der Items läuft mehrere Minuten und damit (gefühlt) um Faktoren länger, also bei der Aktualisierung über evals. Ich habe versucht die DB Zugriffe zu minimieren. Das ergab aber keine Besserung.

    Kannst Du Dir die Logik bitte mal anschauen, ob da strukturell was nicht passt?
    Danke

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Oh, da hast ja Vollgas gegeben, dankeschön!

    Soweit scheint das mal gut zu klappen, muss ich aber noch beobachten. Die Message
    No entries for Item stromverbrauch.energiemodul.c.stand.kwh in DB found for requested end 417450i; oldest entry used instead
    kommt wegen dem "Anfang Jahr gibt es keinen Eintrag", oder? Ich würde das nicht unbedingt als Warnung ausgeben.

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Onkelandy
    Hallo,

    ich habe an der Logik und den beiden structs noch etwas gefeilt.

    Es gibt nun 2 structs, das struct "wertehistorie_total" für ein Item mit stetig steigendem Zählerstand (bspw. Strom) und das struct "wertehistorie_minmax" für ein Item mit Werten in einem bestimmten Bereich (bspw. Temp).

    Die Aktualisierung dieser Items übernimmt eine Logik. In der Logik kann man den Ebenenunterschied zwischen dem "Zähleritem" (dem Item in das immer die aktuellen Werte geschrieben werden) und den Items, die die structs erzeugen, einstellen. Die Konfiguration der Logik für die logic.yaml ist auch in der Logik hinterlegt.
    Die Logic prüft, ob das Plugin "database" aktiv ist. Falls Nein, wird die Logik deaktiviert.

    Es werden 3 Trigger für die Logik unterschieden:
    1. Trigger durch ein Item: In den structs ist je ein Trigger-Item eingebaut, dass bei Aktualisierung des Zähleritems via eval und eval_trigger ebenfalls aktualisiert wird (im struct muss ggf. die Ebene noch noch angepasst werden). Dieses (bzw. alle diese) Trigger-Item(s) triggert die Logik. Mit der Logik werden dann die "dynamischen Werteitems", also alle die, die den neuesten Wert des Zähleritems mit nutzen, aktualisiert. "Dynamischen Werteitems" sind bspw. Verbrauch heute, Verbrauch Woche etc.
    2. Trigger durch crontab: Wird die Logik über den crontab getriggert, werden alle "statischen Werteitems" (wie bspw. gestern, vorgestern, etc) berechnet und der Wert ins jeweilige Item geschrieben. Welche Items berechnet werden, hängt vom Auslösezeitpunkt bzw. Datum ab. So werden Items bspw. für Wochenverbrauch nur zu Wochenbeginn berechnet.
    3. Trigger durch Admin (manuell ausglöst): Hier werden alle "statischen Werteitems" berechnet.

    Ich habe 3 Gists erzeugt:Kannst Du das mal testen?
    Merci!

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Cool wäre noch, wenn man einfach zB über ein Logik-Attribut einstellen könnte, in welchem Unteritem das struct abgelegt wird.
    Schau mal ins Gist. Da gibt es ein Update u.a. mit der Möglichkeit den "level-Unterschied" zwischen Zähleritem und struct einzugeben.

    Zitat von Onkelandy Beitrag anzeigen
    Vielleicht möchte das jemand auch noch mehr verschachteln zB in "historie/min_max" und "historie/zaehler" oder wie auch immer. Was meinst du?
    Wie meinst du das?

    Ich arbeite auch an einer Logik für min/max. Welche Auswertungen nutzt du? Min/Max heute, gestern, letzte 24h....

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Super Arbeit, sieht prima aus. Cool wäre noch, wenn man einfach zB über ein Logik-Attribut einstellen könnte, in welchem Unteritem das struct abgelegt wird. Ich hab zB bei meinen Items eigene Unteritems "min_max" und "wertehistorie". Dann wäre nicht das parent_item relevant, sondern eben die Großeltern. Vielleicht möchte das jemand auch noch mehr verschachteln zB in "historie/min_max" und "historie/zaehler" oder wie auch immer. Was meinst du? Dann test ich die Sache sehr gerne mal. Sollten wir dann jedenfalls in der Doku verewigen... https://www.smarthomeng.de/user/beis...xere-beispiele

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Zeigst du mal deine Logik?
    Klar. Schau mal hier

    Die Logik funktioniert so:


    Für die "statischen" Items, also die, die nicht vom direkt vom ParentItem -dem Zähleritem- abhängen, durchsucht die Logik alle Items nach den entsprechenden Items gemäß dem struct und ermittelt dann die historischen Werte. Gibt es pro Item für keines der beiden Abfragezeiten Einträge in der DB, wird nicht berechnet. Gibt es nur den späteren nicht, gibt es eine Warnung im Log und es wird der älteste Eintrag der DB benutzt.
    Getriggert wird über crontabs. Funktioniert!

    Für die "dynamischen" Items, also die, die sich bei jeder Änderung der vom ParentItem -dem Zähleritem- ändern (heute, woche, monat, jahr), kann die Logik auch die Berechnung durchführen. Allerdings fehlt mir die Idee, wie die Logik getriggert wird. Klar kann man alle Zähleritems als Trigger setzen, ich suche aber etwas generisches. Das was alle Zähleritems gemeinsam haben, ist das struct mit dem Namen "wertehistorie". Das wäre Lösungweg A.

    Als Lösungsweg B könnte man alle Items, die auf "heute" enden als watch_item setzen, aber wie kann man diese Items ändern, so dass die Logik getriggert wird und der Wert dann wirklich per Logik ins Item geschrieben wird?

    Lösungsweg C wäre im struct ein eigenes Item mit festem Namen anzulegen, dass immer dann getriggert wird, wenn das ParentItem sich ändern und damit die Logik auslöst. Das probier ich mal aus.

    Update:
    Im gist findest Du die akutelle Logik und "nabendran" auch das passende struct.
    Umgesetzt ist Lösungsweg C. Klappt gut!
    Zuletzt geändert von Sisamiwe; 12.10.2021, 21:08. Grund: Ergänzung und Hinweis zur aktualsierten Logik

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Ich denke übrigens, dass wir generell die "if .. is not None else 0" Abfrage ersetzen sollten durch "(.. or sh..())" - das würde eine Datenbankabfrage ersparen.

    Zeigst du mal deine Logik? Eigentlich wäre es nicht schlecht, wenn ALLES in der Logik gemacht wird. Oder probierst du das eh? Die Frage verstehe ich aktuell noch nicht ganz.

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Onkelandy
    Ich habe parallel eine Logik erstellt, die auch die Berechnung durchführt. Das ist in Summer übersichtlicher.

    Nun hadere ich nur noch mit den "Live" Einträgen, also heute, woche, monat und jahr. Hier müsste die Logik bei jeder Wertänderung des Parentitems getriggert werden.
    Hier fehlt mir noch die Idee, wie man das generell machen kann.

    Ich könnte mit
    Code:
    watch_item:
        - '*.heute'
        - '*.woche'
        - '*.monat'
        - '*.jahr'
    Auf alle entsprechenden Items hören, aber wie triggere ich diese, ohne den Wert des Parents zu übergeben? Nur eval_trigger ohne eval geht nicht.

    Und für die Überachung der ParentItems habe ich noch keine Möglichkeit gefunden. Die Gemeinsamkeit ist die Verwendung des structs mit bestimmten Namen. Allerdings habe ich keinen Ahnung (deshalb die Frage im Forum), ob es dafür eine Möglichkeit gibt.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Ich hab jetzt rumprobiert und das ganze in einen funktionierenden eval Ausdruck gepackt. Es scheint zu klappen, abgesehen von dem kleinen Problem: der Name des Plugins hängt von der Konfiguration im etc/plugin.yaml ab. Bei mir heißt es zB database_mysql. Das ist aber vernachlässigbar.

    Vielleicht kannst du dennoch mal diesen Code hier testen..?
    Code:
    eval: round((sh...() - (sh...db('max', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i') or sh.plugins.return_plugin('database').readLogs(sh.plugins.return_plugin('database').id(sh.return_item(sh....property.path)), sh.plugins.return_plugin('database').readOldestLog(sh.plugins.return_plugin('database').id(sh.return_item(sh....property.path))))[0][4])), 2)
    Zuletzt geändert von Onkelandy; 11.10.2021, 22:57.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Oha, das ist schon mal cool. Der Eval-String dürfte da aber ziemlich ekelhaft werden hehe.. müsste man mal schauen, ob man das irgendwie sinnvoll mit der Logik kombinieren kann.

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Hätte jemand ne Idee wie man das Problem beim Berechnen der Wertehistorie abfangen kann, wenn zu besagtem Abfragezeitpunkt keine Daten in der Datenbank sind?
    Ich bin ein Stück weitergekommen. Im Database Plugin ist eine Funktion integriert, die den Timestamp des ältesten Eintrags zu einer Item-ID zurückgibt. Ich habe das mal in eine Testlogik gegossen:

    Code:
    #!/usr/bin/env python3
    # db_test.py
    
    plugin = sh.plugins.return_plugin('database')
    id = plugin.id(sh.raumtemp.aussen.nord)
    
    readOldestLog = plugin.readOldestLog(id)
    readOldestLog = datetime.datetime.fromtimestamp(readOldestLog/1000, datetime.timezone.utc).astimezone().strftime('%Y-%m-%d %H:%M:%S %Z%z')  
    
    logger.info(readOldestLog)
    Ausgabe ist:
    Code:
    2021-10-10  17:31:48 INFO     logics.db_test                           2017-08-12 21:04:30 CEST+0200
    Also ist der älteste Eintrag für dieses Item vom 12. Aug 2017.

    Jetzt muss man das nur noch sinnvoll einbauen

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Hätte jemand ne Idee wie man das Problem beim Berechnen der Wertehistorie abfangen kann, wenn zu besagtem Abfragezeitpunkt keine Daten in der Datenbank sind?
    Also ganz konkret.. Ich hab seit Mai 2021 ein neues Item am Start und möchte den max Wert vom Jahr 2021 ermitteln. Hier kommt ein "None" zurück, da zu Beginn des Jahres noch keine Daten vorhanden sind. Es sollte also statt beginning_of_year der Zeitpunkt des ersten db Eintrags für das Item herangezogen werden.

    Selbes Spiel dann halt auch für den Monat. Wenn man ein Item erst am 10. des Monats angelegt hat, man aber am 30. des Verbrauch im laufenden Monat abfragen will.
    Das würde die obigen Abfragen noch ein Stück robuster und wertvoller machen Sisamiwe
    Vielen Dank!

    Einen Kommentar schreiben:


  • Hochpass
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Das läuft soweit prima
    O.k. ein langes Wochenende mit schlechtem Wetter steht vor der Tür. Ich guck mal ob ich das zum laufen kriege.

    Danke!

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Ich nutze bei mir die Logik von #47 und den Code für shtime.py von meinem PR. Das läuft soweit prima
    Genau so mache ich das auch. Funktioniert prima.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Mein PR ist noch offen und muss getestet werden bzw. wollte Msinn das Ganze etwas anders lösen. Ich nutze bei mir die Logik von #47 und den Code für shtime.py von meinem PR. Das läuft soweit prima - ansonsten müsste man sich noch etwas gedulden.

    Einen Kommentar schreiben:

Lädt...
X