Ankündigung

Einklappen
Keine Ankündigung bisher.

Logik für Zirkulationspumpe - meine erste Logik in SmartHome.py

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

    #16
    Zitat von mumpf Beitrag anzeigen
    crontab ist keine Zeiteinschränkung, sondern eine zeitbasierte Aktion. So wie Du das verwendest, bringt das nichts.
    Abend,

    danke Waldemar, das crontab für mein Vorhaben nicht so geeignet ist, das hab ich mir schon gedacht. Schade... Dann müsste ich wohl doch in Richtung Logik gehen.
    Nun ich schau mal das ich mich in python einlese wenn ich Zeit dazu finde....

    Viele Grüße
    Jannis

    Kommentar


      #17
      ???
      Zitat von startrix Beitrag anzeigen
      das crontab für mein Vorhaben nicht so geeignet ist, das hab ich mir schon gedacht.
      Das habe ich nicht gesagt! Du verwendest crontab nur nicht richtig.

      Ich habe Dir doch die Lösung geschrieben? So kannst Du es direkt verwenden...

      Gruß, Waldemar

      Kommentar


        #18
        Zitat von mumpf Beitrag anzeigen
        ???

        Das habe ich nicht gesagt! Du verwendest crontab nur nicht richtig.

        Ich habe Dir doch die Lösung geschrieben? So kannst Du es direkt verwenden...

        Gruß, Waldemar
        Hallo Waldemar, Hallo Foren Gemeinschaft,

        mumpf leider bekomme ich die Lösung wie von dir geschrieben nicht umgesetzt.

        Nun da ich Urlaub habe, hab ich mich aber nochmal mit dem Thema Beschäftigt und versuche das ganze nun via Logik abzubilden.
        Aktuell hab ich das ganze mal für meine Umgebung daheim geschrieben um dies einfach testen zu können.

        Wenn Flur Licht unten angeht, dann schalte auch Flur Licht oben an und nach 5 Sekunden wieder aus.

        Hierzu habe ich folgenden Code in der \etc\logic.yaml:
        Code:
        zirkulation:
            filename: zirkulation.py
            crontab: init
            watch_item: Lampen.Flur_unten.Deckenlampe.schalten
        und folgendes Pyhton Skript erstellt \logics\zirkulation.py
        Code:
        #!/usr/bin/env python3
        # zirkulation.py
        
        if sh.Lampen.Flur_unten.Deckenlampe.schalten():
            sh.Lampen.Flur_oben.Deckenlampe.schalten('on')
            time.sleep(5)
            sh.Lampen.Flur_oben.Deckenlampe.schalten('off')
        Bis dahin funktioniert auch alles wie es soll.

        Nun zur Einschränkung das dies nur zwischen zwei definierten Zeiten passiert:
        Code:
        #!/usr/bin/env python3
        # zirkulation.py
        
        import time
        
        if sh.Lampen.Flur_unten.Deckenlampe.schalten():
            while(True):
                now = time.strftime("%H:%M:%S")
                timewindow1_ok = ("06:00:00") <= now < ("13:00:00")
                if timewindow1_ok:
                    sh.Lampen.Flur_oben.Deckenlampe.schalten('on')
                    time.sleep(180)
                    sh.Lampen.Flur_oben.Deckenlampe.schalten('off')
                    sleep(2)
        Auch dies scheint nach ersten Tests jetzt zu funktionieren.

        Als nächstes dann noch die Bedingung das die Aktion pro Tag nur einmal ausgeführt werden kann. Wenn der Lichtschalter das zweite mal angeht, dann soll der Code nicht ausgeführt werden.

        Ich werde berichten, wenn ich es zum laufen bekomme, und mich dann mal an ein Tutorial setzen.
        Viele Grüße & allen schon mal schöne Feiertage Jannis
        Zuletzt geändert von startrix; 18.12.2018, 12:18.

        Kommentar


          #19
          Hi,

          warum "while(True)"?

          Damit machst Du eine Endlosschleife auf, die nie beendet wird. Anders gesagt: Nach dem ersten betätigen des Schalters wird Dein Licht immer zwischen 6 und 13 Uhr für 3 Minuten eingeschaltet, dann ist es 2 Sekunden aus und dann wieder an etc.

          Ferner wird mit jedem Einschalten am Schalter ein neuer Thread aufgemacht, der nie beendet wird. Beides willst Du nicht!

          Das mit merken, dass es schon an war, ist ganz einfach. Du machst Dir ein Item, dass sich das Einschalten merkt und das (z.B. per crontab) um Mitternacht zurückgesetzt wird. Sobald Du einschaltest, merkst Du Dir das im Item. Bevor Du einschaltest, fragst Du das Item ab.

          Gruß, Waldemar

          Kommentar


            #20
            Zitat von mumpf Beitrag anzeigen
            Hi,
            warum "while(True)"?
            :-( Weil ich Anfänger bin in Dingen python, aber hab mich eben schon in die Schleifen Thematik eingelesen, und gesehen das dies nicht ganz so intelligent war...
            Wie auch immer ich würde das ganze gerne in ein IF ELSE statement nun packen um auch noch eine Unterscheidung zu bekommen ob es Wochenende ist oder nicht.

            Dazu folgender Code:
            Code:
            #!/usr/bin/env python3
            # zirkulation_test.py
            
            import time
            import datetime
            
            now = time.strftime("%H:%M:%S")
            day = time.strftime("%a")
            
            if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                print ("Es ist Wochenende")
            else:
                print (day)
                print (now)
                if sh.Lampen.Flur_unten.Deckenlampe.schalten():
                    now = time.strftime("%H:%M:%S")
                    timewindow1_ok = ("06:00:00") <= now < ("16:00:00")
                    if timewindow1_ok:
                        sh.Lampen.Flur_oben.Deckenlampe.schalten('on')
                        time.sleep(5)
                        sh.Lampen.Flur_oben.Deckenlampe.schalten('off')
                        time.sleep(2)
            Bis zum print (now) Befehl wird es auf der Konsole wieder sauber ausgeführt. Aber leider wird Lampen.Flur_oben.Deckenlampe.schalten wohl nicht mehr ausgeführt...

            Vielleicht brauch ich erst mal ne Pause.

            Das Licht ist übrigens nicht wieder nach den 2sec. Pause angegangen.
            Kannst du mir aber erklären, was es mit den Threads auf sich hat? Der Raspi wurde deutlich langsamer mit der Zeit...

            Viele Grüße
            Jannis

            Kommentar


              #21
              Hi,

              Zitat von startrix Beitrag anzeigen
              Das Licht ist übrigens nicht wieder nach den 2sec. Pause angegangen.
              In dem "While"-Beispiel oben kann das sein, weil da statt "time.sleep(2)" nur "sleep(2)" steht. Das gab dann einen Syntaxfehler und die Schleife wurde nicht erneut ausgeführt.

              Zitat von startrix Beitrag anzeigen
              Aber leider wird Lampen.Flur_oben.Deckenlampe.schalten wohl nicht mehr ausgeführt...
              Wenn was nicht läuft, schaust Du dann ins Log? Da sollte eigentlich drin stehen, wenn was nicht läuft.

              Zitat von startrix Beitrag anzeigen
              Kannst du mir aber erklären, was es mit den Threads auf sich hat?
              Ein Automatisierungssystem wie shNG.py sollte immer laufen, auch wenn die User Logiken und Plugins programmieren und da vielleicht was falsch machen, z.B. durch Syntaxfehler. Wäre ja blöd, wenn dann das gesamte Programm abbrechen würde.

              Also werden Logiken (und auch Plugins) in gesonderten "Laufzeitumgebungen" laufen gelassen, die Threads genannt werden. Wenn hier ein Fehler passiert, dann wird der Thread beendet, aber das Hauptprogramm läuft weiter.

              Wenn man einen Thread mit time.sleep() anhält, hat das auch (glücklicherweise) keine Auswirkungen auf das Hauptprogramm. Der Thread "lebt" aber so lange im Speicher, bis der sleep vorbei ist.

              Wenn man aber in einen Thread eine Endlosschleife einbaut, dann wird der Thread (und damit der benutzte Speicher) nie freigegeben. Ferner belastet die Endlosschleife den Prozessor (sie läuft ja ewig weiter). Deswegen ist das schlecht...

              Wenn man es dann so macht wie Du, dass bei einem Tastendruck ein neuer Thread mit Endlosschleife gestartet wird, führt das zwangsläufig dazu, dass irgendwann der RasPi nicht mehr reagiert. Deswegen sagte ich, dass Du das nicht willst

              Gruß, Waldemar

              Kommentar


                #22
                Guten Morgen Waldemar,

                vielen Dank für die super Erklärung bzgl. den Threads.

                Zitat von mumpf Beitrag anzeigen
                Wenn was nicht läuft, schaust Du dann ins Log? Da sollte eigentlich drin stehen, wenn was nicht läuft.
                Und nochmal Danke, ich vergesse es doch immer wieder das es ja LogFiles gibt die einem Helfen den Fehler zu suchen.
                Also hab ich gleich mal nachgesehen was dort so steht:

                Code:
                2018-12-19  08:15:17 ERROR    logics.zirkulation Logic: logics.zirkulation, File: /usr/local/smarthome/logics/zirkulation_test.py, Line: 10, Method: <listcomp>, Exception: name 'day' is not defined
                Traceback (most recent call last):
                  File "/usr/local/smarthome/lib/scheduler.py", line 493, in _task
                    exec(obj.bytecode)
                  File "/usr/local/smarthome/logics/zirkulation_test.py", line 10, in <module>
                    if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                  File "/usr/local/smarthome/logics/zirkulation_test.py", line 10, in <listcomp>
                    if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                NameError: name 'day' is not defined
                Jedoch irritiert mich die Fehlermeldung jetzt doch sehr. Weil genau das was hier angemeckert wird funktioniert eigentlich in meinen Augen und das die Variable day nicht definiert ist sehe ich auch nicht so. Lasse ich das Skript über die Konsole laufen bekomme ich ja folgende Ausgabe:
                Code:
                [pi@SmartHomeNG ../local/smarthome/logics]$ python3 zirkulation_test.py
                Wed
                09:19:54
                Traceback (most recent call last):
                  File "zirkulation_test.py", line 15, in <module>
                    if sh.Lampen.Flur_unten.Deckenlampe.schalten():
                NameError: name 'sh' is not defined
                Verändere ich nun in der Abfrage den Wert Wed für Mittwoch auf XXX
                Code:
                if not any([char == day for char in ["Mon","Tue","XXX","Thu","Fri"]]):
                Und lasse es dann durch die Konsole laufen bekomme ich auch sauber die Antwort das wir Wochenende hätten:
                Code:
                [pi@SmartHomeNG ../local/smarthome/logics]$ python3 zirkulation_test.py
                Es ist Wochenende
                Mhm, jetzt hab ich erstmal was zum grübeln, der Fehler ist wohl hier https://bugs.python.org/issue21161 beschrieben und wird nicht gefixt. Wie ich den nun aber rausbekomme, sehe ich noch nicht...
                Grüße Jannis
                Zuletzt geändert von startrix; 19.12.2018, 09:48.

                Kommentar


                  #23
                  Losgelöst von Deinem Fehler. Warum löst Du
                  Code:
                  if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                       print ("Es ist Wochenende")
                  nicht einfach so:
                  Code:
                  if not (day in ["Mon","Tue","Wed","Thu","Fri"]):
                       print ("Es ist Wochenende")
                  ?
                  Viele Grüße
                  Martin

                  Stay away from negative people. They have a problem for every solution.

                  Kommentar


                    #24
                    Gut, den Fehler im Log habe ich wegbekommen, in dem ich den Code um die erste Zeile ergänzt habe:

                    Code:
                    globals().update(locals())
                    if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                         print ("Es ist Wochenende")
                    Zitat von Msinn Beitrag anzeigen
                    Losgelöst von Deinem Fehler. Warum löst Du
                    Code:
                    if not any([char == day for char in ["Mon","Tue","Wed","Thu","Fri"]]):
                    print ("Es ist Wochenende")
                    nicht einfach so:
                    Code:
                    if not (day in ["Mon","Tue","Wed","Thu","Fri"]):
                    print ("Es ist Wochenende")
                    ?
                    Msinn - Danke, die Antwort ist wohl weil ich es nicht besser weiß. Dein Code sieht aber deutlich besser aus, werde ich so verwenden, vor allem benötige ich dann auch die Zeile nicht
                    Code:
                    globals().update(locals())
                    . Die Logfile weißt nun keinen Fehler mehr auf. Aber das Licht im Flur oben bleibt weiterhin aus...

                    Ich suche mal weiter.

                    Kommentar


                      #25
                      ...oder noch besser:
                      Code:
                      if day in ["Sat", "Sun"]:
                          print ("Es ist Wochenende")
                      Oder noch besser - ich finde es nicht so toll, mit sprachabhängigen Strings zu arbeiten, wenn es nicht notwendig ist:
                      Code:
                      import datetime
                      ...
                      day = datetime.today().weekday()
                      ...
                      if day >=5:
                      ...
                      Und falls der Fehler oben wirklich an der Liste hängt, würde mein unteres Beispiel das lösen.

                      Gruß, Waldemar

                      Kommentar


                        #26
                        Hi,

                        um besser debuggen zu können, ersetze mal Deine beiden print-Anweisungen durch:

                        Code:
                        logger.info("day: {0}, now: {1}".format(day, now))
                        Dann wird auch in das Log ausgegeben. Du kannst dann weitere logger-Anweisungen machen, damit Du verfolgen kannst, wie weit die Logik kommt.

                        Gruß, Waldemar

                        Kommentar


                          #27
                          Hi,

                          danke für all eure Hilfe, nützlichen Hinweise und eure Geduld. Letztendlich hab ich nun einen funktionierende Logik, wo nur noch die letzte Bedingung fehlt (nur einmal am Tag einschalten) - aber das schieb ich jetzt erstmal hinten an.

                          Hier der Code (welchen ich der Hilfe aus dem Python Forum verdanke https://www.python-forum.de/viewtopic.php?f=31&t=44506:

                          Code:
                          #!/usr/bin/env python3
                          # zirkulation_test.py
                          
                          from datetime import datetime as DateTime, time as Time
                          from time import sleep
                          
                          now = DateTime.now()
                          print(now)
                          
                          if now.isoweekday() in [6, 7]: # 6=Samstag, 7=Sonntag - definiert das an diesen Tagen nicht der ELSE Teil ausgeführt wird, sondern nur der IF Teil
                              exit
                          else:
                              if sh.Lampen.Flur_unten.Deckenlampe.schalten():
                                  if Time(5, 45) <= now.time() < Time(13, 59): # definiert den Zeitraum - Startzeit / Endzeit
                                      sh.Lampen.Flur_oben.Deckenlampe.schalten('on')
                                      sleep(5)
                                      sh.Lampen.Flur_oben.Deckenlampe.schalten('off')
                          Viele Grüße
                          Jannis

                          P.S.: Wenn ich ein Tutorial schreibe - wie und wo speicher ich dieses?

                          Kommentar


                            #28
                            Um nur einmal am Tag zu schalten, kannst Du den Tag in eine persistente Variable schreiben (die behält den Wert zwischen Logik Läufen, nicht jedoch über einen shNG Neustart). Beim Aufruf der Logik kannst Du dann diese Variable testen, ob der Tag noch der gleiche ist und nur schalten, falls das nicht so ist.

                            Wenn Du ein Tutorial schreiben möchtest, wäre ein Blog Artikel auf unserer Website www.shamrthomeng.de der richtige Weg. (Zur Registrierung siehe https://www.smarthomeng.de/registrieren-und-bloggen.)
                            Viele Grüße
                            Martin

                            Stay away from negative people. They have a problem for every solution.

                            Kommentar


                              #29
                              So, nun ist auch die letzte Bedingung gelöst... jetzt kann ich mich die Tage mal an das Tutorial machen.

                              Wenn jemand Verbesserungsvorschläge hatt, gerne her damit, ich vermute mal es wäre auch ohne die Wiederholung im ELIF Teil gegangen...

                              Code:
                              #!/usr/bin/env python3
                              # zirkulation_test.py
                              
                              from datetime import datetime as DateTime, time as Time
                              from time import sleep
                              import time
                              
                              now = DateTime.now()
                              day = time.strftime("%d")
                              
                              f = open("/usr/local/smarthome/logics/today_zirkulation.txt", "r")
                              today_s = f.read()
                              f.close()
                              
                              if day < today_s:
                                  if now.isoweekday() in [6, 7]:
                                      exit()
                                  else:
                                      if sh.Lampen.Bad_Deckenlampe():
                                          if Time(5, 45) <= now.time() < Time(7, 45): # definiert den Zeitraum - Startzeit / Endzeit
                                              sh.Aktor_SiKa_Keller.Zirkulationspumpe('on')
                                              sleep(180)
                                              sh.Aktor_SiKa_Keller.Zirkulationspumpe('off')
                                              today_w = time.strftime("%d")
                                              f = open("/home/smarthome/today_zirkulation.txt", "w")
                                              f.write(today_w)
                                              f.close()
                                              exit()
                              elif day > today_s:
                                  if now.isoweekday() in [6, 7]:
                                      exit()
                                  else:
                                      if sh.Lampen.Bad_Deckenlampe():
                                          if Time(5, 45) <= now.time() < Time(7, 45): # definiert den Zeitraum - Startzeit / Endzeit
                                              sh.Aktor_SiKa_Keller.Zirkulationspumpe('on')
                                              sleep(180)
                                              sh.Aktor_SiKa_Keller.Zirkulationspumpe('off')
                                              today_w = time.strftime("%d")
                                              f = open("/usr/local/smarthome/logics/today_zirkulation.txt", "w")
                                              f.write(today_w)
                                              f.close()
                                              exit()
                              else:
                                  exit()
                              Viele Grüße
                              Jannis

                              Kommentar

                              Lädt...
                              X