Ankündigung

Einklappen
Keine Ankündigung bisher.

Logik bei Item-Änderung - Werte-Historie im Speicher halten?

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

    Logik bei Item-Änderung - Werte-Historie im Speicher halten?

    Hallo,

    ich möchte per watch_item eine Logik an ein Item binden und bei Wertänderungen getriggert werden, so gut, so schön.
    Nun möchte ich allerdings auch etwas wie eine Histerese einbauen und dafür die vorherigen Werte merken.
    Nach meinem Verständnis ist eine Logik ein Python-Script, das stumpf in einem eigenen Prozess ausgeführt wird und sich anschließend wieder beendet.
    Kann ich auch irgendwie Werte/State zwischen den Logik-Triggers halten?

    #2
    Wenn du nur die letzten paar historischeb Werte brauchst, könntest du die Historie in einem zweiten Item vom Typ list halten und per eval_trigger nachführen.

    Kommentar


      #3
      Wenn der letzte Wert genügt geht das sogar Out of the Box mit prev_age() oder prev_value().
      Ansonsten sieht's OOTB finster aus.
      Hysteresen mache ich über Logiken, die bspw. bei Änderung einen Timer triggern der dann nochmal prüft ob nach Zeit x noch immer etwas über/unterschritten ist.

      Kommentar


        #4
        Hallo,

        kannst Du mal ein Beispiel von so einer Hysterese posten?

        Danke und Grüße
        mg

        Kommentar


          #5
          ganz simples "Wenn jetzt-wert +- 10% über/unter vorherigem wert liegt"

          Kommentar


            #6
            ich benutze das jetzt als logik

            logics/telegram.py
            Code:
            #!/usr/bin/env python3
            import telepot
            
            ITEM_BOT_TOKEN = 'telegram_bot_token' 
            ITEM_CHAT_ID   = 'telegram_chat_id'
            ITEM_MESSAGE   = 'telegram_message'
            
            item  = sh.return_item( trigger['source'] )
            
            if ITEM_BOT_TOKEN not in item.conf:
                logger.error('no {} specified'.format(ITEM_BOT_TOKEN))
            
            elif ITEM_CHAT_ID not in item.conf:
                logger.error('no {} specified'.format(ITEM_CHAT_ID))
            
            elif ITEM_MESSAGE not in item.conf:
                logger.error('no {} specified'.format(ITEM_MESSAGE))
            
            else:
                value = trigger['value']
                last_value = item.prev_value()
            
                delta = abs(value - last_value)
                hysteresis = 0.1
                min_delta = abs(value * hysteresis)
            
                logger.info( 'now: {}, was: {}, delta: {}, min-delta: {}'.format(value, last_value, delta, min_delta) )
            
                if delta >= min_delta:
                    logger.info('changed')
                    bot_token = item.conf[ITEM_BOT_TOKEN]
                    chat_id   = item.conf[ITEM_CHAT_ID]
                    message   = item.conf[ITEM_MESSAGE].format(value)
            
                    bot = telepot.Bot(bot_token)
                    bot.sendMessage(chat_id, message)
            etc/logic.conf
            Code:
            [TelegramTaupunktOB]
                filename = telegram.py
                watch_item = kk16.ow.ob.taupunkt
            items/foo
            Code:
            [[[[taupunkt]]]]
                        name = EW Wohnen Taupunkt
                        type = num
                        eval = round(sh.tools.dewpoint(sh.kk16.ow.ew.temp(), sh.kk16.ow.ew.hum()), 1)
                        eval_trigger = kk16.ow.ew.temp | kk16.ow.ew.hum
                        knx_dpt = 9
                        knx_send = 8/2/12
                        knx_reply = 8/2/12
                        telegram_bot_token = 'XXXXXXX'
                        telegram_chat_id   = '124125125'
                        telegram_message   = 'EW Taupunkt: {:.2f}'
            vielleicht hilfts wem - feedback würde mir helfen

            Kommentar


              #7
              Danke.

              Vor einiger Zeit habe ich auch eine logic geschrieben um per Telegram Windwarnungen aufs Handy zu schicken. Bin derzeit am Überlegen, ob es nicht Sinn macht ein Plugin zu schreiben, mit dem man Telegram zentral konfiguriert und dann auf bestimmte Items in der *.conf Datei dranhängen kann.

              [Windalarm]
              type = num
              eval = ...
              eval_trigger = ...
              telegram_notify = 'Nachricht die per Telegram verschickt werden soll'

              Gerne würde ich in den Nachrichtenstring ein paar feste, allgemeine Variablen mit aufnehmen, die dann vor dem Versenden mit realen Werten ersetzt werden.
              Vielleicht macht es auch noch Sinn gewisse Items zu übergeben (z.B. akt. Windgeschwindigkeit), evtl.

              telegram_notify = 'Windalarm: ({:.2f} km/h, {} Bft)'
              telegram_variables = 'AUSSEN.wind.kmh, AUSSEN.wind.bft'

              Die Hysterese habe ich bereits rein über Items ohne spezielle Logik gelöst - ich finde, es macht die Konfiguration/Erweiterung/Wiederverwendung einfacher... nur die Umsetzung von Messageformat und füllen mit Variablen (die ebenso als String übergeben werden) macht mir derzeit Probleme, das stecke ich zu wenig in Python drin..

              Geschickt wäre auch eine Aktivierung / Deaktivierung, sodass man Warnung z.B. je nach Anwesenheit auf einen LED oder Handy umleiten kann...

              Vielleicht können wir ja gemeinsam an so einem Plugin basteln

              Kommentar


                #8
                Ja, bin deiner Meinung. Habe mir schon angeschaut wie plugins strukturiert sind. Meine obige Logik ist nur um das überhaupt mal laufen zu haben.

                Wie hast du die hysterese per item abgebildet?

                Kommentar


                  #9
                  Hi,

                  ich habe von einem Beispiel hier im Form abgekupfert:

                  Code:
                                  [[[warn]]]
                                          name = Warnung Windstärke
                                          type = bool
                                          visu_acl = r
                                          eval = sh.AUSSEN.wind.warn.status() and not sh.AUSSEN.wind.warn.delay()
                                          eval_trigger = AUSSEN.wind.warn.status | AUSSEN.wind.warn.delay
                                          [[[[threshold]]]]
                                                  # Schwelle für die Windgeschwindigkeit
                                                  name = Schaltschwelle Obergrenze (km/h)
                                                  type = num
                                                  visu_acl = rw
                                                  value = 10.0
                                          [[[[status]]]]
                                                  # Wertet die Schaltschwelle aus und implementiert eine Hysterese
                                                  # 0: Wind unter dem Schwellwert
                                                  # 1: Wind über dem Schwellwert
                                                  name = Hysterese Status
                                                  type = num
                                                  eval = 1 if sh.AUSSEN.wind.kmh() > sh.AUSSEN.wind.warn.threshold() else 0 if sh.AUSSEN.wind.kmh() < sh.AUSSEN.wind.warn.threshold() - 1.0 else sh.AUSSEN.wind.warn.status()
                                                  eval_trigger = AUSSEN.wind.kmh | AUSSEN.wind.warn.threshold
                                          [[[[delay]]]]
                                                  # Delayfunktion
                                                  # 1: wenn Status 1
                                                  # 0: wenn Status 0 oder nach Timeout
                                                  name = Verzoegerung
                                                  type = bool
                                                  autotimer = 15 = 0
                                                  eval = value
                                                  eval_trigger = AUSSEN.wind.warn.status

                  Kommentar


                    #10
                    Hallo Zusammen,

                    Frage an die Profis: wie kann man eine "conditional expression" in einem Item Attribut übergeben, welche im Plugin ausgewertet wird?

                    Hintergrund:
                    Das telegram plugin funktioniert dahingehen, dass ich einem Item z.B. das Attribut "Telegram_message = 'Es klingelt an der Tür'" übergebe. Ändert sich dich der Item Wert, so schickt Telegram die Nachricht raus. Die Bedingung, dass das Item sich ändert, lässt sich auch über eval/trigger ohne logic oder plugin einstellen (z.B. nur wenn abwesend oder im garten aktiv). Super, soweit. Nur leider löst jede Änderung eine eine Message aus, einmal wenn der Wert auf "1" geht und wenn der Wert wieder auf "0" geht. Natürlich lässt sich das auch über Support-Items lösen, aber das bläst die Item-Config ziemlich auf.
                    Daher denke als mögliche Erweiterung an
                    - einen Message String mit Variablen Übergabe der zum Sendezeitpunkt noch ein paar Werte mit in den String packt und die Nachricht dynamisch wird.
                    - eine Bedingung welche erfüllt sein muss, damit die Nachricht raus geht. Hier bin ich mir nicht ganz sicher, ob das nicht irgendwie doppelt gemoppelt wird? Aber zumindest einfache Bedingungen (="nur senden wenn von 0->1") erscheinen mir dennoch sinnvoll.

                    Wie sind Eure Meinungen zu diesem Ansatz? Erweitern oder über Items und evals laufen lassen?
                    Habt Ihr so etwas schon einmal (technisch) implementiert und evtl. ein paar code Schnipsel die hier helfen könnten?

                    Gibt es allgemein ein Interesse an einer gemeinsamen Entwicklung von so einem Plugin?

                    Kommentar

                    Lädt...
                    X