Ankündigung

Einklappen
Keine Ankündigung bisher.

eval überschreiben / userfunktion flexibler

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

    #16
    Resümierend (1):

    Code:
    class Item():
        """..."""
        def __call__(self, value=None, caller='Logic', source=None, dest=None):
            if value is None or self._type is None:
            return copy.deepcopy(self._value)
            if self._eval:
                args = {'value': value, 'caller': caller, 'source': source, 'dest': dest}
                self._sh.trigger(name=self._path + '-eval', obj=self.__run_eval, value=args, by=caller, source=source, dest=dest)
            else:
                 self.__update(value, caller, source, dest)
    Bedeutet immer wenn eval gesetzt ist, wird es auch benutzt wenn eine Itemzuweisung der Art sh.Item(value) ausgeführt wird.

    Demzufolge erzeugt eine Itemdefinition wie

    Code:
    Foo:
        type: num
        eval: value+5
        initial_value: 0
    bei einem Aufruf mit
    Code:
    sh.Foo(0)
    auch einen Wert 5 des Items.

    Alternativ kann man den Wert eines Items auch über seine (private) Methode __update__() setzen:

    Code:
    sh.Foo._Item__update(0)
    dann bekommt das Item den Wert 0.

    PS: (1) hat in SmartHomeNG 1.5.1 so ausgesehen:
    Code:
        def __call__(self, value=None, caller='Logic', source=None, dest=None):
            if value is None or self._type is None:
                return self._value
            if self._eval:
                args = {'value': value, 'caller': caller, 'source': source, 'dest': dest}
                self._sh.trigger(name=self._path + '-eval', obj=self.__run_eval, value=args, by=caller, source=source, dest=dest)
            else:
                self.__update(value, caller, source, dest)
    nur um klarzustellen das es da in letzter Zeit keine Änderung wesentlicher Art gab.
    Zuletzt geändert von bmx; 06.03.2022, 13:54.

    Kommentar


      #17
      Zitat von bmx bmx Beitrag anzeigen
      nur um klarzustellen das es da in letzter Zeit keine Änderung wesentlicher Art gab.
      Danke Bernd, gut zu wissen - das hat ja dann auch Auswirkungen auf alle anderen Zuweisungen, z.B. über autotimer & co, Logiken etc. Egal von wo ich etwas zuweise, eval haut immer nochmal dazwischen. Muss man halt wissen.

      Ich habe gerade nochmal in den Uralt-Code von Marcus geschaut, da schaut es ähnlich aus - Asche auf mein Haupt, irgendwie hab ich mich wohl komplett falsch erinnert. Ich war mir zu 100% sicher, dass ich das schon anders verwendete habe (Stichwort: Not-Ausschalter), und dass das Verhalten mal anders war.

      Bleibt also z.B. der Lösungsansatz von Onkelandy, wenn man das eval stoppen will; oder der Weg über Hilfsitems. Und für die Zukunft auf der Wunschliste ein weiteres Attribut 'eval_trigger_only' o.ä., welches ein eval nur triggert, wenn die dort explizit genannten Sender die Wertveränderung bzw. das Update veranlassen.

      /tom
      Zuletzt geändert von Tom Bombadil; 06.03.2022, 14:36.

      Kommentar


        #18
        Also ich bin nach wie vor für die Lösung mit zusätzlichem if Statement.

        Allerdings: es muss trigger_by und nicht change_by genutzt werden! Bin da selbst letztens drüber gestolpert, weshalb es seit 1.9.1 neue Properties gibt. Siehe Doku.

        Ein weiteres dezidiertes Attribut wäre aber auch eine Überlegung wert. Wenn denn würde ich aber vorschlagen, das mittels regex feinkörnig einstellbar zu machen. Standardmäßig müsste natürlich das Verhalten bleiben wie es ist, aber zB Überschreiben möglich durch..
        Code:
        eval_calc_by:
           - onchange (mit der Möglichkeit, auch genauer zu spezifizieren, z.B. onchange:Item1)
           - item1 (zB ident wie in eval_trigger)
           - Database:init
           - ...
        Theoretisch könnte man auch mit dem Listeneintrag "eval_trigger" automatisch 1:1 die Einträge aus dem eval_trigger Attribut übernehmen oder so..?
        Was meint ihr?
        Zuletzt geändert von Onkelandy; 07.03.2022, 23:03.

        Kommentar


          #19
          Zitat von Onkelandy Onkelandy Beitrag anzeigen
          Was meint ihr?
          Mir ist das zu kompliziert. Mir wäre es wichtig, dass ich ein Item entweder direkt oder über den Bus überschreiben kann, obwohl da ein eval_trigger drin ist. Ich habe dazu gerade mal was gebastelt, muss das aber erst mal noch testen, deshalb ist das nur so eine Art Ansatz mit User-Funktion:

          Item:

          Code:
          Test:
              eItem1:
                  type: bool
                  eval: value if uf.itools.ntr(sh.self) else True if sh.Test.eItem2() == 2 else False
                  eval_trigger: Test.eItem2
          
              eItem2:
                  type: num
          User-Funktion:

          Code:
          def ntr(item):
              if item.property.last_trigger_by == '': return True
              return False
          So könnte man dass auch machen, wenn es geht, eben mit einer User-Funktion. Aber besser wäre schon ein direktes Attribut dafür zu haben.

          Kommentar


            #20
            last_trigger_by wird nie leer sein. Wenn du also das Item über KNX aktualisiert hast, steht da "KNX:g/a" drin. Die User Function müsste am ehesten so heißen
            Code:
            if not item.property.last_trigger_by.lower().startswith("eval")
            Wir müssten halt mal Ideen bzw. Situationen sammeln, wo ein "Nichtauslösen" vom eval gewünscht ist. Entsprechend sollte das Attribut umgesetzt werden. Könnte mir zB eine Mischung aus den Vorschlägen vorstellen..

            Persönlich denk ich aber, dass - wenn das wie beschrieben funktioniert - absolut ausreichend und übersichtlich genug ist. Also
            Code:
            eval: value if not sh..self.property.last_trigger_by.lower().startswith("eval") else True if sh.Test.eItem2() == 2 else False

            Kommentar


              #21
              Zitat von Onkelandy Beitrag anzeigen
              last_trigger_by wird nie leer sein. Wenn du also das Item über KNX aktualisiert hast, steht da "KNX:g/a" drin. Die User Function müsste am ehesten so heißen
              Ich versuche das gerade auf dem Weg, aber die Übergabe des Items selbst macht Schwierigkeiten:

              Code:
              Test:
                  eItem1:
                      type: bool
                      eval: value if uf.itools.ntr(sh..self) else True if sh.Test.eItem2() == 2 else False
                      eval_trigger: Test.eItem2
              Das sollte aber meiner Meinung nach so gehen. Im Log kommt dann eine Fehlermeldung, dass er das Item "sh.Test.eItem1.self" nicht evaluieren kann. Eigentlich sollte doch sh..self das hier sein: sh.Test.eItem1 oder?

              Kommentar


                #22
                Stimmt - man kann das Item selbst leider nicht in "relativer" Form an eine Funktion schicken. Wollte das mal fixen, bin aber gescheitert. Ich hab mal n Issue auf Github gestellt, vielleicht bekommt das Msinn hin https://github.com/smarthomeNG/smarthome/issues/481

                Was jedenfalls gehen wird, ist Folgendes:
                sh..self.property.path

                Und dann musst du in der Funktion das return_item nutzen: https://smarthomeng.de/user/referenz...ht=return_item
                Oder eben.. solange es noch so simpel ist, würd ich das ohne Userfunctions machen.

                Kommentar


                  #23
                  Zitat von Onkelandy Msinn Beitrag anzeigen
                  Was jedenfalls gehen wird, ist Folgendes:
                  sh..self.property.path

                  Und dann musst du in der Funktion das return_item nutzen: https://smarthomeng.de/user/referenz...ht=return_item
                  Oder eben.. solange es noch so simpel ist, würd ich das ohne Userfunctions machen.
                  Ja ich verstehe das Prinzip.

                  Zitat von Onkelandy Beitrag anzeigen
                  last_trigger_by wird nie leer sein. Wenn du also das Item über KNX aktualisiert hast, steht da "KNX:g/a" drin. Die User Function müsste am ehesten so heißen Code:

                  if not item.property.last_trigger_by.lower().startswith(" eval")
                  Die Variante habe ich gestetet und zumindest im Admin-Interface geht es wie gewünscht. Ich befürworte allerdings immer noch ein alternatives EVAL. Es müssen auch keine tausenden Konstellationen und Möglichkeiten sein, sondern, dass das neue EVAL nur dann ausgeführt wird, wenn es über eval_trigger kam. Man kann sich dann sicherlich noch überlegen. Und wenn beide eval angegeben werden, kann man sicherlich das so prüfen, dass das alte EVAL nur dann ausgeführt wir, wenn es NICHT über den trigger kam. Beides wäre ziemlicher Unsinn.

                  Kommentar


                    #24
                    Hab mal n Issue erstellt: https://github.com/smarthomeNG/smarthome/issues/483
                    Gerne weitere Ideen und Kommentare dort einfügen.
                    Denke auch, es sollte möglichst simpel sein - und wenn man's komplexer braucht, kann man das über ne userfunction abfangen.

                    Kommentar


                      #25
                      Zitat von Onkelandy Beitrag anzeigen
                      Hab mal n Issue erstellt: https://github.com/smarthomeNG/smarthome/issues/483
                      Gerne weitere Ideen und Kommentare dort einfügen.
                      Denke auch, es sollte möglichst simpel sein - und wenn man's komplexer braucht, kann man das über ne userfunction abfangen.
                      Danke sehr!!!

                      Kommentar

                      Lädt...
                      X