Ankündigung

Einklappen
Keine Ankündigung bisher.

Stateengine Plugin Support

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

  • Onkelandy
    antwortet
    gama Ich hab nun ein großes Update zum Plugin am Start, kannst du es bitte testen? Am besten den Branch runterladen und den stateengine Ordner ersetzen (gerne zuvor Backup ) https://github.com/onkelandy/plugins...ne/stateengine

    Die wichtigste Neuerung für se_use: Structs lassen sich nun über struct:stateengine.state_lock.rules.lock einbinden. Auch eigene! Außerdem kann man nun auch Listen angeben, evals, Items, etc. Wenn man se_use mit eval nutzt, wird der State zur Laufzeit vor dem Check neu generiert. Dadurch wäre ne ganze Menge möglich. Und das se_name Attribut wird nun auch etwas optimierter eingebunden (hoffe ich).

    Allerdings muss ich gestehen, fehlt mir die Idee, wie man nun am einfachsten einen guten suspend State hinbekommt, der durch einen anderen State "aufgelöst" wird und dann aber wieder aktiv wird. Meine ursprüngliche Vision wäre gewesen, dass man Dank dynamischem se_use einfach immer state_suspend nutzen kann und die restlichen Bedingungen kommen dann zur Laufzeit vom vorigen Zustand (zB Nacht) dazu. Aber da ja alle Aktionen auch übernommen werden, ist es kein suspend mehr. Das se_use sorgt ja für einen "gesamten Merge" beider Stati. Hoffe, du konntest folgen

    Man müsste also so oder so einen eigenen suspend_nacht Zustand erstellen. Dort dann mit se_use den suspend einbinden. Allerdings müssen dann alle Bedingungssets gleich heißen wie im struct, damit's gemergt wird. Irgendwie ne Sackgasse - aber du hattest oben von Ideen geredet... bitte gerne

    Einen Kommentar schreiben:


  • gama
    antwortet
    Ideen hätte ich schon, sind aber an objektorientierte Programmierung angelehnt, die mit einfachen structs nicht funktionieren - deshalb dachte ich, dass se_use vielleicht eine Alternative ist. Ich denke, die Einfachheit wird im aktuellen Status Quo so erreicht, dass man möglichst viele fertige structs von states im plugin.yaml hat. Und ein zweiter, anpassbarer suspend ist sicher nicht verkehrt.

    Ich habe zwei States, bei denen ein bestehender suspend aufgelöst werden soll: ASLEEP (Nacht) und COOLING_AWAY. Cooling Away macht dicht, wenn es zu warm und niemand mehr im Haus ist. FREE ist der Default Status (es wird weder Position noch Winkel gestellt) und kann nicht per stetting deaktiviert werden.

    Denkbar wären noch UNLOCKED_WINDOW, sollte z.B. ein Fenster geöffnet werden, fährt der Rolladen hoch (z.B. Brand), sofern man das nicht direkt am Aktor mit einer Fahrbegrenzung löst.

    Somit wäre meine State Reihenfolge:

    lock:
    suspend_v1:
    ASLEEP:
    UNLOCKED_WINDOW:
    COOLING_AWAY
    suspend:
    PRIVACY
    COOLING
    OPEN:
    FREE:

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Ich habe gestern mal mit ein paar Ideen gespielt, alles noch nicht so prickelnd. Was ich jedenfalls machen werde, ist beim struct mehrere suspenddurations einstellen zu lassen. Und se_suspend_time wird dann immer mit einer passenden Durationsetting bestückt, abhängig von einem numerischen Wert in einem "suspendvariation" Item. Dieses würde also durch die anderen States, zB Nacht gesetzt werden. Das funktioniert soweit mal prima und ich denke mit nem einfachen Beispiel auch verständlich.

    Probleme macht definitiv das se_use. Das hab ich nicht mehr getestet und da passt einiges nicht. Andererseits wäre es der richtige Ansatz, um einen eigenen Suspend State auf Basis des bestehenden zu erstellen.. structs sind hier leider zu unflexibel. Ich schau mir das nochmals an mit dem se_use.

    Ein anderer Ansatz wäre, beim suspend Item einfach noch ein zusätzlich bool Item abzufragen (für jede "Variant" ein anderes). Auch das wäre einfach im struct zu lösen, ist aber glaub nicht sonderlich komfortabel. Denn dann bräuchte es einen Zustand "drüber", der zuerst den bool Wert setzt und anschließend in den darunter liegenden speziellen Suspend State wechselt.

    Falls du gama eine generelle Idee hast, wie man die Funktionalität einfach und nutzerfreundlich bereitstellen könnte, lass es mich bitte wissen.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    gama - du versuchst offenbar mit se_use auf ein struct zuzugreifen, das geht natürlich nicht. Du müsstest dir ein struct mit den stateengine.state_x zusammenbauen und darauf fann referenzieren. Wobei ich denke, dass das Hauptitem nicht gleich wie das Plugin heißen sollte.. Ich bin aber zuversichtlich,dass ich was Einfacheres hinbekomme.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Ich hab den Code aus dem plugin.yaml in ein struct kopiert und binde das ein. se_use schau ich mir bei Gelegenheit mal an, aber ich denke grad über eine Erweiterung des Suspend Zustands im plugin.yaml nach, damit man den auch zumindest 2 Mal mit unterschiedl. Dauer und versch. Conditions einfach nutzen kann.

    Kannst du dir bitte den aktuellsten Stand von meinem Repo ziehen und mal "generell" testen? Es gab noch einige Änderungen. Wichtig wäre, dass alles min. so gut läuft wie bisher

    Einen Kommentar schreiben:


  • gama
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Das suspend_nacht ist hinsichtlich der Aktionen eine 1:1 Kopie aus dem suspend struct der plugin.yaml. Die Bedingungen sehen so aus:
    Ich wollte mit se_use: stateengine.state_suspend.rules.suspend nur den state übernehmen, was nicht funktioniert hat...
    hast du den code 1:1 aus der plugin.yaml kopiert oder benutzt du struct bzw. se_use?


    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Du könntest für unterschiedliche Suspendzeiten ja auch einfach die Variable se_suspend_time entsprechend befüllen. Dürfte eigentlich kein Problem sein..

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Hab ich aktuell tatsächlich.. ich hab aber auch noch einen anderen Status, bei dem die "Suspend Zeit" weniger lang ist.. dieser wird eingenommen, wenn ich eine bestimmte Taste drücke und sieht dann so aus..

    Code:
    beschattung_se_state_taster:
        status:
            taster:
                type: bool
                eval: or
                crontab: init
                eval_trigger:
                    - ....kz.taster
                    - ....lz.taster
    
                start:
                    date_time:
                        type: str
                        visu_acl: ro
                        cache: True
    
                    unix_timestamp:
                        remark: Can be used for the clock.countdown widget
                        type: num
                        visu_acl: ro
                        eval: "0 if sh...date_time() in ['', ' '] else sh.tools.dt2ts(shtime.datetime_transform(sh...date_time())) * 1000"
                        eval_trigger: ..date_time
                        crontab: init
    
        settings:
            taster:
                aktiv:
                    type: bool
                    visu_acl: rw
                    cache: True
                    initial_value: True
    
                dauer:
                    type: num
                    cache: True
                    initial_value: 10
    
                    duration_format:
                        type: str
                        visu_acl: ro
                        eval: "'{}h {}i 0s'.format(int(sh...()//60), round((sh...()%3600)%60))"
                        eval_trigger: ..
                        crontab: init
    
        rules:
            se_item_taster_start: ..status.taster.start.date_time
            se_item_taster_kz: ...kz.taster
            se_item_taster_lz: ...lz.taster
    
            taster:
                name: taster
    
                on_enter_or_stay:
                    se_action_retrigger:
                      - 'function: special'
                      - 'value: retrigger:..retrigger'
                      - 'delay: eval:se_eval.get_relative_itemvalue("..settings.taster.dauer") * 60 - se_eval.get_relative_itemproperty("..state_name", "last_change_age")'
                on_enter:
                    se_action_taster_start:
                      - 'function: set'
                      - 'to: eval:str(shtime.now())'
    
                on_leave:
                    se_action_taster_kz:
                      - 'function: set'
                      - 'to: False'
                    se_action_taster_lz:
                      - 'function: set'
                      - 'to: False'
                    se_action_taster_start:
                      - 'function: set'
                      - 'to:  '
                      - 'delay: 1'
    
                enter_manuell:
                    se_value_trigger_source:
                      - eval:se_eval.get_relative_itemid('...kz.taster')
                      - eval:se_eval.get_relative_itemid('...lz.taster')
    
                enter_stay:
                    se_value_laststate: var:current.state_id
                    se_max_age: eval:se_eval.get_relative_itemvalue('..settings.taster.dauer') * 60

    Im Übrigen ist der neue Release zum Testen bereit. Bin gespannt, was alles schiefgeht am besten machst du davor ein backup von deinem cache Verzeichnis. Ich hab jetzt ein Item suspendduration.seconds. Das befüllt das Nicht-seconds automatisch und umgekehrt.
    Ist aber sonst auch einiges geändert, da es doch noch ein paar Problemchen gab..
    https://github.com/onkelandy/plugins...ne/stateengine

    Einen Kommentar schreiben:


  • gama
    antwortet
    Ok, dann hast Du für suspend_nacht die gleiche Dauer wie das Standard suspend, oder?

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    se_state_nacht sieht inkl. Templates so aus:
    Code:
    beschattung_se_template_helligkeit:
        rules:
            se_template_nacht_max_helligkeit: eval:se_eval.get_relative_itemvalue('..settings.nacht.max_helligkeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else se_eval.get_relative_itemvalue('{}.stateengine.settings.nacht.max_helligkeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og')))
            se_template_nacht_max_helligkeit_hysterese: eval:400 + (se_eval.get_relative_itemvalue('..settings.nacht.max_helligkeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else  se_eval.get_relative_itemvalue('{}.stateengine.settings.nacht.max_helligkeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og'))))
            se_template_nacht_forced_max_helligkeit: eval:se_eval.get_relative_itemvalue('..settings.nacht.forced_max_helligkeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else se_eval.get_relative_itemvalue('{}.stateengine.settings.nacht.forced_max_helligkeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og')))
            se_template_abend_max_helligkeit: eval:se_eval.get_relative_itemvalue('..settings.abend.max_helligkeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else se_eval.get_relative_itemvalue('{}.stateengine.settings.abend.max_helligkeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og')))
            se_template_abend_max_helligkeit_hysterese: eval:400 + (se_eval.get_relative_itemvalue('..settings.abend.max_helligkeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else  se_eval.get_relative_itemvalue('{}.stateengine.settings.abend.max_helligkeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og'))))
    
    beschattung_se_typ:
        settings:
            beschattungstyp:
                type: str
                cache: True
                eval: >-
                  "screens" if sh..self.property.path.startswith(("screens", "markise")) else
                  "jalousien.kino" if (sh..self.property.path.split('.')[-4] in ["osten_wohnen", "osten_stiegenhaus", "sueden_stiegenhaus"]) else
                  "jalousien.og" if ("jalousien.og." in sh..self.property.path) else
                  "jalousien.eg" if ("jalousien.eg." in sh..self.property.path) else
                  "unknown"
                enforce_updates: True
                crontab: init = 'nothing'
    
    beschattung_se_state_nacht:
        settings:
            nacht:
                hoehe:
                    type: num
                    visu_acl: rw
                    cache: True
                lamellen:
                    type: num
                    visu_acl: rw
                    cache: True
                aktiv:
                    type: bool
                    visu_acl: rw
                    cache: True
    
        rules:
            se_item_nacht_aktiv: ..settings.nacht.aktiv
            se_item_hoehe: ...hoehe
            se_item_lamellen: ...lamellen
            se_item_helligkeit: wetterstation.helligkeit.maximal
            se_template_nacht_start: eval:se_eval.get_relative_itemvalue('..settings.nacht.startzeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else se_eval.get_relative_itemvalue('{}.stateengine.settings.nacht.startzeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og')))
            se_template_nacht_end: eval:se_eval.get_relative_itemvalue('..settings.nacht.endzeit') if se_eval.get_relative_itemvalue('..settings.beschattungstyp') == 'jalousien.eg' else se_eval.get_relative_itemvalue('{}.stateengine.settings.nacht.endzeit'.format(se_eval.get_relative_itemvalue('..settings.beschattungstyp').replace('jalousien.kino', 'jalousien.og')))
    
            nacht:
                name: nacht
    
                on_enter_or_stay:
                    se_action_hoehe:
                      - 'function: set'
                      - 'to: item:..settings.nacht.hoehe'
                      - 'order: 1'
                    se_action_lamellen:
                      - 'function: set'
                      - 'to: item:..settings.nacht.lamellen'
                      - 'order: 2'
    
                enter:
                    se_max_helligkeit: template:nacht_max_helligkeit
                    se_value_nacht_aktiv: True
                    se_min_time: '09:00'
                    se_max_time: '16:00'
                    se_negate_time: True
    
                enter_hysterese:
                    se_max_helligkeit: template:nacht_forced_max_helligkeit
                    se_value_laststate:
                      - var:current.state_id
                      - eval:se_eval.get_relative_itemid('..rules.suspend_nacht')
                    se_value_nacht_aktiv: True
                    se_min_time: '09:00'
                    se_max_time: '16:00'
                    se_negate_time: True
    
                enter_zeit:
                    se_value_laststate:
                      - var:current.state_id
                      - eval:se_eval.get_relative_itemid('..rules.suspend_nacht')
                    se_value_nacht_aktiv: True
                    se_min_time: template:nacht_end
                    se_max_time: template:nacht_start
                    se_negate_time: True
    
        struct:
            - beschattung_se_typ
            - beschattung_se_template_helligkeit
    Das suspend_nacht ist hinsichtlich der Aktionen eine 1:1 Kopie aus dem suspend struct der plugin.yaml. Die Bedingungen sehen so aus:
    Code:
                enter_manuell_nacht:
                    se_value_laststate: eval:se_eval.get_relative_itemid('..rules.nacht')
                    se_value_nacht_aktiv: True
                    se_min_time: '09:00'
                    se_max_time: '16:00'
                    se_negate_time: True
                    se_value_trigger_source: eval:se_eval.get_relative_itemid('..manuell')
                    se_value_suspend_active: True
                enter_stay:
                    se_value_laststate: var:current.state_id
                    se_agemax_suspend: var:item.suspend_time
                    se_value_suspend: True
                    se_value_suspend_active: True

    Einen Kommentar schreiben:


  • gama
    antwortet
    Könntest Du mal
    - beschattung_se_state_suspend_nacht
    - beschattung_se_state_nacht
    posten?

    Ich möchte nachts oder während der Abwesenheit nur ein kurzes suspend fahren.
    Dabei übernehme ich den suspend state aus der plugin.yaml per se_use: stateengine.state_suspend.rules.suspend und muss beim Eintritt die se_suspend_time sichern und dann überschreiben, oder? Wie machst Du das?

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Die Nachtsettings nutze ich global für mehrere Zustände, daher als getrenntes struct. Aber normalerweise hab ich ja settings und rules auch in einem struct (so wie im plugin.yaml ja auch).
    Suspend_nacht ist bei mir ein eigener State mit anderen Aktionen als Nacht. Daher zwei unterschiedliche structs. Aber ja, klar, man könnte die auch zusammenfassen, zB als sub-structs. Aber das wäre für mich wieder verwirrend, da ich dann im Item selbst nicht direkt sehe, was ich da genau konfiguriert habe..

    Einen Kommentar schreiben:


  • gama
    antwortet
    Das Testen übernehme ich gerne.
    Einen Gedanken hätte ich noch, da ich gerne einen Status inkl. zugehörigen Settings in ein Struct (quasi als Modul) zusammenfassen möchten:

    Aktuell nutzt Du ja auch 3 getrennte Templates für einen zusätzlichen Status:
    - beschattung_se_nachtsettings
    - beschattung_se_state_suspend_nacht
    - beschattung_se_state_nacht

    Da beschattung_se_nachtsettings eigentlich keine Reihenfolge benötigt und *_nacht zusammen liegen, könnten doch alle 3 structs zusammengeführt werden, oder übersehe ich da was?

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Ne, ich bin da ganz bei dir, dass es möglichst einfach sein soll. Daher bin ich von der prio Sache noch nicht ganz überzeugt Das mit den Sekunden macht aber Sinn. Ich bin da eh schon dran, muss noch intensiv testen und werden dann einen PR erstellen. Musst also nix selbst basteln, nur dann testen.

    Einen Kommentar schreiben:


  • gama
    antwortet
    Für mich war halt die Frage, wie jemand der mit stateengine Neuland betritt, möglichst schnell einen Einstieg und das System zum Laufen bekommt. Daher die Frage, ob es einen speziellen Grund für das Minutenraster gibt. Natürlich, kann man (bzw. ich für meine Installation) eigene Konfigurationen erstellen, aber es wäre m.E. für die Verbreitung und Akzeptanz von StateEngine ein weiterer Schritt... ist aber nur eine Anregung und soll nicht bedeuten, dass jetzt das Plugin meinetwegen geändert werden soll. Ich kann das auch drumherum bauen - ist wirklich kein Problem.

    Einen Kommentar schreiben:

Lädt...
X