Ankündigung

Einklappen
Keine Ankündigung bisher.

Haus Status FSM - autoblind?

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

    Haus Status FSM - autoblind?

    Hallo Zusammen,

    vor ein paar Wochen habe ich an anderer Stelle einmal darüber im Forum "nachgedacht", den Haus Status als State Machine darzustellen. Nun möchte ich an die Umsetzung gehen - gerne so, dass diese für Andere auch nutzbar ist.

    Soweit ich informiert bin, ist autoblind der richtige Ansatz, aber eine Warnung im GitHub wiki macht mir etwas sorgen, da der Hausstatus schon von Bedeutung sein wird:
    Wichtig: Es ist nicht empfehlenswert das AutoBlind Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird daher dringend dazu geraten, solche Funktionen unabhängig von smarthome.py und dem AutoBlind Plugin zu realisieren. Für das Hochfahren von Jalousien bei Windalarm beispielsweise sollte die Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen!
    Zur Implementierungsidee:

    Im ersten Schritt sollen zunächst 4 Zustände implementiert werden:
    1. at home
    2. leaving home
    3. away
    4. coming home
    Die "Zwischen-Zustände" 2 und 4 sollen (ähnlich wie beim Auto) Beleuchtungskomfort oder aktivieren der Alarmanlage dienen.

    Die Hauptzustände sollen im zweiten Schritt noch mit Optionen detailliert werden können, z.B. "1.1 Party", "1.2 Übernachtungsgäste" als vererbter Zustand "at home" um Heizung (im Gästezimmer), Beleuchtung oder Rasenmäher entsprechend zu verwalten.

    Auch "away" solle den Unterzustand "holiday" automatisch per timeout aktivieren, wenn zwischenzeitlich kein Wechsel zu "at home" eingetreten ist.

    In der dritten Phase könnte man sich vorstellen, den Zustandsautomat auf "Wohneinheiten" wie Zimmer oder Etagen herunter zu brechen und daraus Übergeordnete Zustände abzuleiten - aber das ist sicher noch ein paar Code Zeilen entfernt.

    Somit zur eigentlichen Frage:
    Haltet Ihr aufgrund Eurer Erfahrung nach autoblind für so einen Haus-Zustands-Automat geeignet, oder sollte man besser mit einem eigens dafür entwickelten plugin auf der grünen Wiese starten?

    #2
    Hi,

    ich habe autoblind jetzt fast 2 Jahre lang am laufen (seit dem es das Plugin gibt). Es ist sehr stabil und funktioniert zuverlässig. Das von Dir erwähnte Zitat auf GitHub ist doch klar nachvollziehbar - warum sollte man als Plugin-Entwickler die Verantwortung für den Einsatz des Plugins übernehmen sollen?

    Ich würde so was mit autoblind machen. Bin allerdings inzwischen auf callidomus und werde es mit der dort bald verfügbaren StateMachine machen.

    Gruß, Waldemar

    Kommentar


      #3
      Hi, danke für die Rückmeldung. Dann werde ich mal starten...

      Da ich in autoblind nicht so tief drin bin vielleicht noch eine Frage vorab:

      Lassen sich die Zustände von autoblind mit mehreren KNX GA verbinden und die GAs wiederum als Trigger für den Statuswechsel verwenden?

      Hintergrund: ich möchte den aktuellen Status per boolean auf den Bus geben, z.b, at home, leaving, away, coming home.
      Ich muss also, wenn ein neuer Status aktiv, wird ein ganzes Item-Set in Abhängigkeit vom Zustand updaten.
      Auf der anderen Seite, möchte ich, dass ein Zustand über eine GA getriggert werden kann (z.B. einfacher Taster).

      Zuletzt sollen die "Unter-Zustände" des Haus mit erfasst werden, die genau genommen keine Zustände sind, sondern eher "Optionen" da diese konkurrierend aktiviert werden können. Es können z.B. gleichzeitig "Übernachtungsgäste" und "Party" aktiv sein. Ist jedoch eine Option gewählt, so soll zwingend der Haus-Zustand auf "at home" gesetzt werden und alle "Unter-Zustände" des vorherigen Zustands gelöscht werden.

      Details wurden vor längerer Zeit bereits unter https://knx-user-forum.de/forum/supp...ustandswechsel diskutiert.

      Beispiel Use-Case:

      Taster triggert HAUS.mode.leaving = 1
      Zustand: leaving (Aktionen: Sofern dunkel Weglicht an, restliches Licht aus), Timer für nächsten Zustand triggern

      Nach 5 Minuten und keiner Bewegungsmedlung: Zustand: away (Alarmanlage scharf, Heizung Standby, etc.), autoblind setzt HOME.mode.away = 1 und restliche bool Items auf 0

      Nach 1 Tag: Holiday (Option unter "away") aktivieren (Heizung auf Frostschutz, Anwesenheitsimulation ein)

      per Remote Zugriff oder Timer: Option Holiday wird deaktiviert -> Zustand "away" (Heizung auf Standby)

      Trigger HAUS.mode.cominghome = 1 (Alarm deaktiviert, Anwesenheitssimulation aus, alle "away Optionen" deaktivieren, Empfangsbeleuchtung, Heizung auf Komfort, etc.)

      Trigger HAUS.mode.athome = 1 (Normalen Hausbetrieb aktivieren, andere Zustände und Unteroptionen deaktivieren)

      Einladung, 2 Option werden geschalten:
      - "Übernachtungsgäste" = 1 (Unteroption von "athome", aktivert z.B. zusätzliches Orientierungslicht, Sauroboter sperren)
      - "Party" = 1 (Unteroption von "athome", Beleuchtung, Bewässerung sperren)

      Trigger HAUS.mode.athome = 1 (Normalen Betrieb wieder herstellen)


      Vielleicht habt ihr gute strukturelle Ansätze um die FSM von Anfang an gut zu strukturieren...

      Kommentar


        #4
        So, erster Entwurf ist fertig und die Grundfunktionen laufen...

        Aber es gibt bereits ein paar Fragen:
        - Ich möchte in den Zustand "away" wechseln, wenn das Alter von "leaving" über dem Grenzwert liegt. Das Funktioniert gut über as_agemin_leaving = 20, aber dazu muss die Zustandsermittlung in kurzen Intervallen aufgerufen werden, erzeugt somit unnötig Last durch das "Polling" und hat zu 99,9% keine Auswirkung auf den Zustandswechsel. Hat hier schon jemand in Kombination mit (auto-)timer - z.B. auf ein Trigger-Item gesetzt - eine auf Events basierende Lösung?
        - Macht es Sinn die (boolean) Status-Items unter HAUS.mode.state.* für den KNX-Signalaustausch tatsächlich in separaten Items (und somit redundant) zu führen, oder kann man diese auch direkt mit den Zuständen der FSM verknüpfen?

        Zuletzt:
        Gibt es bei sh.py die Möglichkeit über Testskripte ein Plugin zu testen, sprich Test-Vektoren konfigurieren, Ereignis auslösen, ggf. warten und mit dem Ziel-Vektor vergleichen? Vielleicht hat ja jemand eine Idee, was fertig oder ich bau mir ein eigenes Skript (z.B. CLI Fernbedienung über TCP)...

        Hier die Aktelle Config:

        Code:
        [HAUS]
                [[mode]]
                        name = Haus Zustand
                        [[[fsm]]]
                                [[[[state_id]]]]
                                        type = str
                                        name = ID des aktuellen Zustands
                                        visu_acl = r
                                        cache = yes
                                [[[[state_name]]]]
                                        type = str
                                        name = Name des aktuellen Zustands
                                        visu_acl = r
                                        cache = yes
                                [[[[rules]]]]
                                        type = bool
                                        name = FSM Haus Modus
                                        as_plugin = active
                                        as_startup_delay = 30
                                        as_laststate_item_id = HAUS.mode.fsm.state_id
                                        as_laststate_item_name = HAUS.mode.fsm.state_name
        
                                        # TRIGGER für Zustandsermittlung
                                        cycle = 60
                                        # crontab = ...
                                        # eval_trigger = HAUS.mode.state.athome | HAUS.mode.state.leaving | HAUS.mode.state.away | HAUS.mode.state.cominghome
                                        eval_trigger = HAUS.mode.state.*
        
                                        # ITEM Definitionen
                                        as_item_athome     = HAUS.mode.state.athome
                                        as_item_leaving    = HAUS.mode.state.leaving
                                        as_item_away       = HAUS.mode.state.away
                                        as_item_cominghome = HAUS.mode.state.cominghome
                                       [[[[[STATE_athome]]]]]
                                                type = foo # Zustand
                                                name = Zuhause
                                                # AKTIONEN
                                                as_set_athome      = 1
                                                as_set_leaving     = 0
                                                as_set_away        = 0
                                                as_set_cominghome  = 0
                                                [[[[[[enter_manuell]]]]]]
                                                        as_value_trigger_source = HAUS.mode.state.athome
                                                        as_value_athome = 1
                                        [[[[[STATE_leaving]]]]]
                                                type = foo # Zustand
                                                name = Gehen
                                                # AKTIONEN
                                                as_set_athome      = 0
                                                as_set_leaving     = 1
                                                as_set_away        = 0
                                                as_set_cominghome  = 0
                                                [[[[[[enter_manuell]]]]]]
                                                        as_value_trigger_source = HAUS.mode.state.leaving
                                                        as_value_leaving = 1
                                        [[[[[STATE_away]]]]]
                                                type = foo # Zustand
                                                name = Abwesend
                                                # AKTIONEN
                                                as_set_athome      = 0
                                                as_set_leaving     = 0
                                                as_set_away        = 1
                                                as_set_cominghome  = 0
                                                [[[[[[enter_manuell]]]]]]
                                                        as_value_trigger_source = HAUS.mode.state.away
                                                        as_value_away = 1
                                                [[[[[[enter_leaveing_age]]]]]]
                                                        as_value_leaving = 1
                                                        as_agemin_leaving = 20
                                        [[[[[STATE_cominghome]]]]]
                                                type = foo # Zustand
                                                name = Heimkehren
                                                # AKTIONEN
                                                as_set_athome      = 0
                                                as_set_leaving     = 0
                                                as_set_away        = 0
                                                as_set_cominghome  = 1
                                                [[[[[[enter_manuell]]]]]]
                                                        as_value_trigger_source = HAUS.mode.state.cominghome
                                                        as_value_cominghome = 1
                        [[[state]]]
                                [[[[athome]]]]
                                        name = Zuhause
                                        type = bool
                                        visu_acl = rw
                                        knx_dpt = 1
                                        knx_listen = 15/7/10
                                        knx_send = 15/7/10
                                        [[[[[guests]]]]]
                                                name = Gäste
                                        [[[[[party]]]]]
                                                name = Party
                                        [[[[[hangover]]]]]
                                                name = Ausschlafen
                                [[[[leaving]]]]
                                        name = Gehen
                                        type = bool
                                        visu_acl = rw
                                        knx_dpt = 1
                                        knx_listen = 15/7/20
                                        knx_send = 15/7/20
                                [[[[away]]]]
                                        name = Abwesend
                                        type = bool
                                        visu_acl = rw
                                        knx_dpt = 1
                                        knx_listen = 15/7/30
                                        knx_send = 15/7/30
                                        [[[[[holiday]]]]]
                                                name = Urlaub
                                                type = bool
                                                visu_acl = rw
                                                knx_dpt = 1
                                                knx_listen = 15/7/35
                                                knx_send = 15/7/35
                                [[[[cominghome]]]]
                                        name = Heimkehren
                                        type = bool
                                        visu_acl = rw
                                        knx_dpt = 1
                                        knx_listen = 15/7/40
                                        knx_send = 15/7/40

        Kommentar


          #5
          Zitat von gama Beitrag anzeigen
          - Ich möchte in den Zustand "away" wechseln, wenn das Alter von "leaving" über dem Grenzwert liegt. Das Funktioniert gut über as_agemin_leaving = 20, aber dazu muss die Zustandsermittlung in kurzen Intervallen aufgerufen werden, erzeugt somit unnötig Last durch das "Polling" und hat zu 99,9% keine Auswirkung auf den Zustandswechsel. Hat hier schon jemand in Kombination mit (auto-)timer - z.B. auf ein Trigger-Item gesetzt - eine auf Events basierende Lösung?
          Klar, sobald Du in den Zustand leaving gehst, setzt Du ein Item auf 1, das wiederum selbst über autotimer nach 21 Sekunden auf 0 geht. Das triggert dann wiederum autoblind.

          Zitat von gama Beitrag anzeigen
          - Macht es Sinn die (boolean) Status-Items unter HAUS.mode.state.* für den KNX-Signalaustausch tatsächlich in separaten Items (und somit redundant) zu führen, oder kann man diese auch direkt mit den Zuständen der FSM verknüpfen?
          Ja, das geht soviel ich weiß nicht anders.

          Zitat von gama Beitrag anzeigen
          Gibt es bei sh.py die Möglichkeit über Testskripte ein Plugin zu testen, sprich Test-Vektoren konfigurieren, Ereignis auslösen, ggf. warten und mit dem Ziel-Vektor vergleichen? Vielleicht hat ja jemand eine Idee, was fertig oder ich bau mir ein eigenes Skript (z.B. CLI Fernbedienung über TCP)...
          Du könntest einen Äquivalenten Automaten bauen, der statt über KNX über das nw-Plugin kommuniziert und dann passend die IP-Pakete setzen/testen. Ist nur eine Idee, aber erfordert Doppelpflege...

          Gruß, Waldemar


          Kommentar


            #6
            Danke für Dein Feedback...

            Das Problem mit dem autotimer ist nach wie vor, dass man die Laufzeit "hart" codieren muss. Elegant wäre eine Zeiteinstellung per Item, sodass man z.B. über Schieber in der VISU das Modul konfigurieren kann.
            Es gibt hier im Forum ein paar Beispiele, die über Hilfsitems und wieder zyklischen Polling arbeiten. Ein Workaround wäre evtl. eine kleine Logik, die Änderungen abfängt und den variablen Timer indirekt setzt. Letztendlich könnte man auch gleich den Funktionsumfang von autoblind erweitern, da Timeouts m.E. schon bei komplexeren FSM vorkommen... aber mir fehlt (noch) aufgrund mangelnder Detailkenntnis von autoblind der richtige Ansatz für so eine Funktion...
            Wie siehst Du das? Soll ich mal ein Feature Request per Issue aufmachen?

            Kommentar


              #7
              Zitat von gama Beitrag anzeigen
              Das Problem mit dem autotimer ist nach wie vor, dass man die Laufzeit "hart" codieren muss.
              Hast Du das mal probiert? Ich habe die Helligkeitsschwellen (ab wieviel Helligkeit die Jalousien in den Sonnenschutz gehen sollen) als Schieberegler konfiguriert. Dieses Item habe ich dann statt des Helligkeitswertes in meine Konfiguration vom autoblind eingetragen und es hat funktioniert. Irgendetwas in der Art muss doch auch bei Timer gehen...

              Gruss Andreas

              Kommentar


                #8
                Hi,

                folgende Idee:
                Mach ein String-Item, dessen Wert in der Form
                Code:
                time;item;value
                
                z.B.
                60;Test.Trigger;7
                geschrieben wird. Du machst eine kleine Logik, die per coding einen Timer auf das Item mit dem Wert setzt nach der angegebenen Zeit. Schon kannst Du von autoblind aus auf dieses Item schreiben (im richtigen Format) und bekommst Deinen dynamischen Trigger.

                Gruß, Waldemar

                Kommentar


                  #9
                  McTao: "einfache" Werte / Variablen funktionieren, aber Timer gehen (bislang) nicht.

                  mumpf, dann kann ich aber keine einfachen Visu-Objekte nutzen, um z.B. die Laufzeit zu verändern, oder?

                  Ich brauche irgendwas in der Art:

                  HAUS.mode.config.leaving_time = 60

                  und einen Autotimer der anstatt mit
                  Code:
                  [item]
                      autotimer = 60 = 1
                  als

                  Code:
                  [item]
                      autotimer = HAUS.mode.config.leaving_time = 1
                  funktioniert. Zudem müsste der Timer aktualisiert werden, sofern sich der Wert von leaving_time ändert.

                  Insgesamt finde ich den Ansatz diskussionswürdig :
                  - auf der einen Seite werden alle (automatischen) Zustandswechsel durch autoblind und Eintrittsbedingungen verwaltet.
                  - jetzt kommen (externe) Hilfskonstrukte hinzu um eine fehlende Implementierung auszubügeln.
                  - auf der Anderen Seite hätten auch andere Code-Schnipsel (die nicht autoblind einsetzen) was davon, wenn die Parameter von autotimer dynamisch einstellt werden könnten.

                  Ich habe bei autoblind mal ein issue aufgemacht. Mal sehen was der Entwickler dazu meint...

                  Wer wäre der Ansprechpartner für so eine Erweiterung bei sh.py? Ich habe mir mal die core Funktionen angesehen, stecke aber (noch) zu wenig im Detail drin um die autotimer Erweiterung allein umsetzen zu können...

                  Kommentar


                    #10
                    Moin, irgendwie versteh ich ehrlich gesagt nicht so ganz wo das Issue bei sh.py sein soll (zu autoblind kann ich leider nix sagen)..... Du mußt das eben in einer Logik abfrühstücken und kannst das nicht mit eval machen.
                    Mal so als Snip aus einer Logik:
                    Code:
                            if trigger['source'].endswith('Stromwert') and TargetDeviceItem.schalten.Timerautomatik.helper() == False and TargetDeviceItem.Stromwert() < Threshold:
                                TargetDeviceItem.schalten.Timerautomatik.helper(1)
                                TargetDeviceItem.schalten.Timerautomatik.helper[B].timer(Timer, 0)[/B]
                    Der Wert für Timer wird in der Logik aktuell aus einem Value gezogen, kann man aber auch über ein Item machen was dann via slider in der Visu gesteuert wird.

                    Kommentar


                      #11
                      i-am-offline hat geantwortet: es gibt as_delay_...! Das sollte mein Problem lösen. Ich melde mich, wenn ich weiter bin. Danke!

                      Kommentar


                        #12
                        as_delay habe ich mehrfach im Einsatz und funzt wunderbar.. Nutze ich u.a. eben dazu, die Abfrage des Zustands in x Minuten nochmals zu triggern.

                        Unabhängig davon fände ich es schon auch fein, wenn in smarthome.py der autotimer über ein Item gesteuert werden könnte. Könntest ein Issue auf github eröffnen, dann kümmert sich vielleicht wer drum

                        Kommentar


                          #13
                          Ich habe gerade noch folgendes Problem:

                          Das Item wird nach vergebener Zeit auf den vorgegeben Wert gesetzt, jedoch triggert die Zustandsermittlung nicht... Wenn ich das Item von Hand setze, läuft autoblind... Hast Du eine Ahnung woran das liegen könnte? https://github.com/i-am-offline/smar...blind/issues/4

                          Hast Du ein Implementierungsbeispiel zu as_delay_... ?

                          Kommentar


                            #14
                            Ich seh gerade, dass ich bei mir doch kein Retriggern der Zustandsabfrage über as_delay drin hab.
                            Wenn ich das Problem aber richtig sehe, dann musst du mit einem Hilfsitem anrücken, das du mittels as_delay aufrufst.

                            Dein sh.HAUS.mode.state.away sollte dann auf das Hilfsitem mittels eval und eval_trigger reagieren. Dadurch müsste verhindert werden, dass das eval direkt vom AutoBlind kommt - es kommt jetzt ja von einem Item.

                            Kommentar


                              #15
                              Hi,

                              man braucht kein Hilfsitem. Man muss nur das Autoblind-Item (also das, an dem der Zustandsautomat hängt, das also alle cycle, eval_trigger usw. für den Automaten trägt) mit irgendeinem Wert beschreiben. Dann wird das Ding getriggert und wertet sich neu aus.

                              Gruß, Waldemar

                              Kommentar

                              Lädt...
                              X