Ankündigung

Einklappen
Keine Ankündigung bisher.

Eval und Autotimer gemeinsam im Item

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

    Eval und Autotimer gemeinsam im Item

    Hallo!

    Ich nutze sh.py aus dem Dev Tree und möchte nun gerne die "Waschmaschine fertig" (oder ähnliches) Meldung implementieren, da ich keine Logik dafür bauen wollte, bräuchte ich ein eval, welches den Wert nur auf 1 setzt und per Autotimer wieder zurücksetzt, geht das?

    Was ich bisher versucht habe ist:

    Code:
                [[[[Trockner]]]]
                    type = bool
                    knx_dpt = 1
                    knx_send = 1/1/10
                    knx_cache = 1/0/10
                    visu_acl = rw
                    [[[[[Stromwert_kWh]]]]]
                        type = num
                        knx_dpt = 9
                        knx_cache = 2/2/10
                        visu_acl = rw
                        sqlite = true
                    [[[[[InBetrieb]]]]]
                        type = bool
                        visu_acl = rw
                        eval = True if sh.Trockner.Stromwert_kWh() > 0.02
                        eval_trigger = Trockner.Stromwert_kWh
                        autotimer = 10m = 0
    funktioniert leider nicht, da bekomme ich eine Fehlermeldung

    Code:
    2015-05-20 14:52:25 WARNING  Trockner.InBetrieb Item Trockner.InBetrieb: problem evaluating True if sh.Trockner.Stromwert_kWh() > 0.02: unexpected EOF while parsing (<string>, line 1)
    Danke und Grüße
    David

    #2
    Hallo David,

    rein von der Klammeranzahl zu sehen fehlen einige Anteile (in Klammern) bei sh.[].Trockner.Stromwert und auch bei eval.

    Michel

    Kommentar


      #3
      Hallo,

      da fehlt auch noch ein else:
      https://www.python.org/dev/peps/pep-0308/

      Bis bald

      Marcus

      Kommentar


        #4
        Zitat von mknx Beitrag anzeigen
        Hallo,

        da fehlt auch noch ein else:
        https://www.python.org/dev/peps/pep-0308/

        Bis bald

        Marcus
        Hallo Marcus!

        Genau das ist meine Frage: kann ich ein true setzen ohne einen false-Wert anzugeben. Ziel ist es, den Wert von .InBetrieb auf 1 zu setzen, sobald ein Stromwert größer 20 Watt kommt und dann den Autotimer ticken zu lassen, bis entweder erneut eine Leistungsaufnahme größer 20 Watt gemeldet wird oder halt die 10 Minuten um sind, dann könnte ich beim Wechsel von InBetrieb auf 0 eine Logik rennen lassen

        PS: Die Klammern fehlen, weil das Ganze nur ein angepasster Auszug aus der items.conf ist.

        Danke und Grüße
        David

        Kommentar


          #5
          Hallo David,
          Zitat von kingolli Beitrag anzeigen
          Genau das ist meine Frage: kann ich ein true setzen ohne einen false-Wert anzugeben.
          genau genommen nein, es spielt aber hier keine Rolle ob Du einen zusätzlichen False-Wert angibst. Du musst aber einen "alternativen" Wert angeben.
          Das kann z.B. auch None sein, dann wird das eval in der weiteren Bearbeitung ignoriert.

          Bis bald

          Marcus

          Kommentar


            #6
            Zitat von mknx Beitrag anzeigen
            Hallo David,

            genau genommen nein, es spielt aber hier keine Rolle ob Du einen zusätzlichen False-Wert angibst. Du musst aber einen "alternativen" Wert angeben.
            Das kann z.B. auch None sein, dann wird das eval in der weiteren Bearbeitung ignoriert.

            Bis bald

            Marcus
            Hallo Marcus!

            'None' habe ich zufällig auch gerade probiert, das scheint erstmal zu funktionieren: der Wert wird korrekt gesetzt und nicht zurückgesetzt, wenn der Verbrauch unter 20 Watt sinkt, allerdings wird auch der Autotimer nicht ausgeführt, der wird wird also nie wieder 0.

            Der Eintrag sieht jetzt so aus:

            Code:
                            [[[[[InBetrieb]]]]]
                                type = bool
                                visu_acl = rw
                                eval = True if sh.Trockner.Stromwert_kWh() > 0.02 else None
                                eval_trigger = KG.Trockner.Stromwert_kWh
                                autotimer = 1m = False
                                enforce_updates = true
            Hast du noch eine Idee, ansonsten mach ich es per Logik.

            Danke und Grüße
            David

            Kommentar


              #7
              Sorry, es spielt hier doch ein Rolle, da wenn der Autotimer greift das eval noch mal ausgewertet wird. Und dann steht da "None" und dann wird alles weitere ignoriert.

              Bis bald

              Marcus

              Kommentar


                #8
                Hi,

                ich benutze immer statt dem None einfach das Item selbst - das wird wahrscheinlich Dein Problem lösen.
                Hoffe es hilft,

                Gruß, Waldemar
                OpenKNX www.openknx.de

                Kommentar


                  #9
                  Hallo Kingolli,

                  Hast du das Problem gelöst bekommen ? Ich würde gerne eine Prowl Nachricht schicken wenn der Trockner fertig ist. Ein MDT Stromaktor liefert den Stromwert.
                  Das Problem ist, wie wahrscheinlich bei dir auch, der Knitterschutz. Nach dem Trockenvorgang läuft der jede Minute für 10 Sekunden. Allerdings ist das ein Stromwert < 1 A.

                  Momentan habe ich
                  Code:
                      [[Trockner]]
                          [[[Strom]]]
                              type = num
                              visu_acl = rw
                              sqlite = yes
                              knx_dpt = 14
                              knx_listen = 5/1/1
                              knx_init = 5/1/1
                          [[[Betrieb]]]
                              type = bool
                              visu_acl = rw
                              eval = True if sh.Technik.Trockner.Strom() > 1 else None
                              eval_trigger = Technik.Trockner.Strom
                              autotimer = 1m = False
                              enforce_updates = true
                  Das Problem ist dass Autotimer den eval auslöst, was an sich normal ist da er ja den Wert des Items verändert. Allerdings scheint er eval auszulösen bevor er den Wert setzt ? Eigentlich müsste der Autotimer ja nach 1 Minute den Wert auf False setzen, eval auslösen welches bei None ankommt und das wars. Leider bleibt der Wert aber auf True und wird nicht auf false zurückgesetzt.

                  Ich habe auch

                  Code:
                   eval = True if sh.Technik.Trockner.Strom() > 1 else sh.Technik.Trockner.Betrieb()
                  ausprobiert wir von Mumpf vorgeschlagen. Allerdings bleibt der Wert auf True da er ja auch True ist vor dem Eval und wie gesagt Autotimer anscheinend den Wert nicht vor dem eval setzt ?

                  Wo ist mein Denkfehler ?


                  Edit: Hier noch ein Log

                  Code:
                  2015-09-15 10:34:47,374 DEBUG    Main         knx: 1.1.1 set 5/1/1 to 12.119999885559082 -- __init__.py:parse_telegram:198
                  2015-09-15 10:34:47,375 DEBUG    Main         Item Technik.Trockner.Strom = 12.119999885559082 via KNX 1.1.1 5/1/1 -- item.py:__update:373
                  2015-09-15 10:34:47,378 DEBUG    Main         Triggering Technik.Trockner.Betrieb - by: KNX source: 1.1.1 dest: 5/1/1 value: {'value': 12.119999885559082, 'source':  -- scheduler.py:trigger:164
                  2015-09-15 10:34:47,379 DEBUG    Technik.Trockner.Betrieb Triggering Trockner_Betrieb - by: Item source: Technik.Trockner.Betrieb dest: None value: True -- scheduler.py:trigger:164
                  
                  2015-09-15 10:34:50,372 DEBUG    Main         knx: 1.1.1 set 5/1/1 to 0.0 -- __init__.py:parse_telegram:198
                  2015-09-15 10:34:50,373 DEBUG    Main         Item Technik.Trockner.Strom = 0.0 via KNX 1.1.1 5/1/1 -- item.py:__update:373
                  2015-09-15 10:34:50,377 DEBUG    Main         Triggering Technik.Trockner.Betrieb - by: KNX source: 1.1.1 dest: 5/1/1 value: {'value': 0.0, 'source': 'Technik.Trockn -- scheduler.py:trigger:164
                  2015-09-15 10:34:50,378 INFO     Technik.Trockner.Betrieb Item Technik.Trockner.Betrieb: evaluating True if sh.Technik.Trockner.Strom() > 1 else None returns None -- item.py:__run_eval:344
                  
                  2015-09-15 10:35:47,743 DEBUG    Technik.Trockner.Betrieb-Timer Triggering Technik.Trockner.Betrieb-eval - by: Autotimer source: None dest: None value: {'value': 'False', 'source': None, 'call -- scheduler.py:trigger:164
                  2015-09-15 10:35:47,744 INFO     Technik.Trockner.Betrieb-eval Item Technik.Trockner.Betrieb: evaluating True if sh.Technik.Trockner.Strom() > 1 else None returns None -- item.py:__run_eval:344
                  Zuletzt geändert von Foxi352; 15.09.2015, 10:41.

                  Kommentar


                    #10
                    Hi,

                    ich weiß nicht, ob man vom Denkfehler sprechen kann... ich versuch mal das Umfeld zu erklären:

                    Du gehst davon aus, dass ein Item-Wert gesetzt wird und danach das eval läuft, das diesen Wert korrigiert. Das ist aber nicht der Fall. Ein Item wird nur einmal gesetzt! Sonst würden ja abhängige Logiken potentiell mehrmals getriggert, welchen Wert sollten die dann nehmen?

                    Der Ablauf ist folgendermaßen (nur plakativ, den genauen Ablauf müsste man im Coding nachvollziehen):
                    • Das Item bekommt einen neuen Wert gesetzt (durch knx, 1-Wire, durch eine Logik oder sonst irgendwas).
                    • Dieser Wert wird in die variable "value" geschrieben
                    • Es wird geschaut, ob ein eval existiert, falls nein, wird eval = value angenommen.
                    • jetzt wird eval(value) ausgeführt
                    • Das Ergebnis vom eval wird ins Item geschrieben
                    • jetzt wird noch geschaut , ob der neue Wert anders ist als der alte oder ob enforce_updates = true ist, falls eines zutrifft, werden abhängige Logiken getriggert.
                    Der obige Ablauf zeigt, dass ein eval IMMER vor dem setzen des Items läuft, aber auch, dass man "value" im eval abfragen kann. Oder noch anders gesagt: Wenn der eval läuft, dann können die Werte vom "value" und vom Item, in dem der eval läuft, durchaus unterschiedlich sein!

                    Ferner muss man noch bedenken, dass value den Wert des Triggernden Items annimmt, bei Dir also vom Strom(), also ein num, und vom autotimer, also ein bool.

                    Zu Deinem Problem:
                    Du setzt das Item nie auf False! Einfach nur auf True wenn der Strom > 1 ist.
                    Es muss einfach
                    Code:
                    eval = True if sh.Technik.Trockner.Strom() > 1 else value if type(value) is bool else None
                    heissen.

                    Gruß, Waldemar
                    OpenKNX www.openknx.de

                    Kommentar


                      #11
                      Danke Waldemar. Deine Erklärungen haben mir sehr viel beim Verständnis geholfen.
                      Leider funktioniert das Setzen auf "False" immer noch nicht. Der Autotimer wird korrekt ausgeführt, das eval kommt aber immer noch zu dem Ergebnis "None"

                      Code:
                      2015-09-15 14:30:08,105 DEBUG    Technik.Trockner.Betrieb-Timer Triggering Technik.Trockner.Betrieb-eval - by: Autotimer source: None dest: None value: {'value': 'False', 'dest': None, 'caller -- scheduler.py:trigger:164
                      2015-09-15 14:30:08,106 INFO     Technik.Trockner.Betrieb-eval Item Technik.Trockner.Betrieb: evaluating True if sh.Technik.Trockner.Strom() > 1 else value if type(value) is bool else None returns None -- item.py:__run_eval:344
                      Ich hab auch mit
                      Code:
                      eval = True if sh.Technik.Trockner.Strom() > 1 else value if isinstance(value,bool) else None
                      probiert mit dem gleichen Resultat.
                      Auch mir Klammern das gleiche Resultat
                      Code:
                      eval = True if sh.Technik.Trockner.Strom() > 1 else (value if isinstance(value,bool) else None)
                      Ich hatte es in meiner Verzweiflung sogar so probiert
                      Code:
                      eval = if sh.Technik.Trockner.Strom() > 1: True elif isinstance(value,bool): value else None
                      hat aber nur Fehler generiert
                      Zuletzt geändert von Foxi352; 15.09.2015, 14:02.

                      Kommentar


                        #12
                        Hi,

                        sorry, das mit type() habe ich nicht ausprobiert, bin derzeit am arbeiten... isinstance geht nur bei Klassen, oder? Da kommen wieder meine geringen python-Kenntnisse durch...

                        Ein Versuch wäre auch
                        Code:
                        eval = True if sh.Technik.Trockner.Strom() > 1 else value
                        Das Problem ist, ich weiß nicht genau, was Du willst. Du hast 3 Fälle, in denen Dein Item getriggert wird:
                        1. Strom > 1 => da soll es True werden
                        2. value = False => da soll es False werden
                        3. Strom <= 1 => was soll da passieren? Im letzten Vorschlag sollte da ein None kommen
                        In dem Vorschlag hier würde für Strom <= 1 auch ein True kommen, außer der Strom ist = 0. Falls Du das sowieso willst, kannst Du das nehmen.

                        Ansonsten fällt mir nichts mehr ein. Ich melde mich heut Abend nochmal, wenn ich das mit type() ausprobiert habe.

                        Gruß, Waldemar
                        OpenKNX www.openknx.de

                        Kommentar


                          #13
                          Soweit ich weiss ist in Python > 2.2 Int eine Klasse, und Bool ist eine Subklasse davon. Ausser ich irre mich gewaltig. Also müsste isinstance funktionieren. Findet man auch so bei Google.

                          Was ich will ? Das fragt mich meine Frau auch immer :-)

                          Hier der Versuch einer Erklärung;

                          Bei einer Waschmaschine oder einem Trockner gibt es ein paar Probleme wenn man relativ zuverlässig einen "in Betrieb" Status haben will:

                          1. Während dem Betrieb kommt es manchmal (vor allem bei der Waschmaschine) zu kurzen Pausen für ein paar Sekunden wo der Strom sehr klein wird (Trommel steht). Da soll natürlich nicht direkt ein "AUS" kommen. Das war ja auch die initiale Frage vom OP.
                          2. Nach dem Programm gibt es den Knitterschutz der für eine halbe Stunde (je nach Modell) läuft. Dann hast du ungefähr 60 Sekunden einen kleinen Strom, und dann wieder 10 Sekunden einen grösseren Strom. Da aber die Heizung da nicht mehr mitläuft ist der bei meinem Trockner z.B. immer < 1A. Das heisst für Eval soll das auf 0 bleiben.
                          3. Auch wenn die Maschinen komplett stehen können mal kurz Ströme > 0A aufkommen, z.B. beim Öffnen der Tür. Dann soll sie natürlich nicht sofort wieder auf "EIN" springen.


                          Um diese Probleme zu lösen will ich folgende 2 Sachen die sich leicht anhören aber scheinbar kompliziert umzusetzen sind :-S :

                          1. Wenn der Strom > 1A springt soll der Status auf "True" springen. Das kann nur vorkommen wenn die Machine wirklich in Betrieb ist.
                          2. Wenn der Strom länger als 1 Minute < 1A bleibt dann soll der Status auf "False" springen da die Machine dann aus oder im Knitterschutz ist was ja auch ein Programmende ist.

                          Der WAF vom Smarthome würde damit ins unendliche steigen wenn ich das zuverlässig hinkriege und dann eine Nachricht per Prowl auf's iPhone schicke :-)

                          Kommentar


                            #14
                            Hi,

                            ich hoffe das ist das, was Du gebrauchen kannst - ich kann das aber bei mir nicht ausprobieren. Bei Strom und Betrieb musst Du noch Deine Properties ergänzen. Ich verwende dieses Pattern bei mir immer, wenn es um irgendwelche Nachlaufzeit geht.

                            Code:
                                [[Trockner]]
                                    [[[Strom]]]
                                        type = num
                                        name = Stromwert
                                    [[[Betrieb]]]
                                        type = bool
                                        eval = value
                                        eval_trigger = Technik.Trockner.Betrieb.Minute
                                        [[[[Minute]]]]
                                            name = Lief in der letzten Minute
                                            type = num
                                            value = 2
                                            autotimer = 1m = 2
                                            eval = sh.Technik.Trockner.Betrieb.Messen() if int(value) > 1 else 1
                                            eval_trigger = Technik.Trockner.Betrieb.Messen
                                        [[[[Messen]]]]
                                            type = bool
                                            eval = sh.Technik.Trockner.Strom() > 1
                                            eval_trigger = Technik.Trockner.Strom
                            Die Idee ist folgende:
                            1. Messen wird true wenn Strom > 1 und triggert Minute, das wird 1, egal was es war, Minute triggert Betrieb, das wird true
                            2. Wenn der Strom jetzt mehr als eine Minute true bleibt, schlägt der Autotimer zu und sendet eine 2. Die führt dazu, dass Minute = Messen wir, also true, Betrieb bleibt wie es ist
                            3. Wenn der Strom unter 1 fällt, wird Messen false und triggert Minute mit value = false. Da der Wert nicht größer als 1 ist, bleibt Minute auf 1 und Betrieb auch.
                            4. Nach einer Minute schlägt wieder der Autotimer zu, triggert Minute mit value = 2 und der eval setzt Minute auf Messen, welches 0 ist. Damit wird Betrieb 0 eine Minute nachdem der Strom aus ist.
                            5. Wenn Messen während der Laufzeit des autotimer wieder 1 werden sollte, so triggert es den autotimer nach und der eval liefert immer noch eine 1.
                            Somit sollte dieses Coding das erfüllen, was Du willst.

                            Gruß, Waldemar
                            OpenKNX www.openknx.de

                            Kommentar


                              #15
                              Sorry Waldemar, aus irgendeinem Grund habe ich deine Antwort erst jetzt gesehen. Hab wohl die Mail übersehen.
                              Ich werde es am Wochenende testen und dir natürlich Feedback geben. Nicht dass du denkst ich würde nicht mal Bescheid geben wenn's denn läuft :-)

                              Serge

                              Kommentar

                              Lädt...
                              X