Ankündigung

Einklappen
Keine Ankündigung bisher.

KNX-Präsenzmelder, temporär sperren

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

    KNX-Präsenzmelder, temporär sperren

    Eigentlich suche ich seit Jahren schon nach einer einfacher Lösung den Präsenzmelder (MDT) in bestimmten Situationen sperren zu können. Das Ganze ist immer relativ aufwändig über mehrere Logiken. Nun wollte ich das ändern, damit es übersichtlicher ist und das direkt in SmartHomeNG umsetzen. Es läuft aber nicht erwartungsgeäß, weil die Sperre nicht mehr aufzuheben ist. Sinn und Zweck ist das Licht mit dem Präsenzmelder zu schalten, gleichzeitig aber auch mit einem Tastsensor und auch mit der SmartVISU.

    Mittels Sperre_erlauben kann man überhaupt festlegen, ob der entsprechende Päsenzmelder (mit der Betätigung des Tastsensors AUS) gesperrt werden kann, mit automatisch_entsperren legt man fest, dass die Sperre beendet wird, wenn die Rolläden sich entweder komplett geöffnet oder komplett geschlossen haben. Das soll man dann in der VISU pro Raum auch konfigurieren können.

    Das Problem ist aber der Punkt schalten. Ich habe es bewusst so gelegt, dass ich dort 2 lesende Adressen eingefügt habe. Denn an knx_send und an knx_listen ist der Tastsensor angebunden, dessen Gruppenadresse am externen Tastereingang des PM angebunden ist. Dennoch möchte ich aber ermitteln, ob das Licht an ist, was ich mit knx_cache an der GA des Schaltaktors gemacht habe, um das in der Visu anzuzeigen. Und da wird ein wenig kompliziert. Denn ich möchte:

    - am Tastsensor an- und aussschalten können
    - in der Visu an- und ausschalten können (Ersatz für Tastsensor)
    - Statusrückmeldungen sowohl in der Visu (auch bei Neustart) als auch in KNX

    Das Problem ist nun, dass der gesperrte Präsenzmelder sich nicht wieder wecken lässt, zumindest nicht nach einer Betätigung. Ich habe das zwar versucht zu lösen, indem ich "- .self = True if value and not sh...sperren() and not sh...sperren.prev_value() else None" zugefügt habe, weil der PM natürlich nicht angeht, aber das geht auch nicht. Gibt es da schlauere Lösungen?

    Hier der Code aus meinem Item-struct:

    Code:
    # Schalten und ggf. Präsenzmelder (Licht/DALI) sperren
    Schalten_mit_Sperrfunktion:
        schalten:
            type: bool
            knx_dpt: 1
            visu_acl: rw
            on_change:
                - ..sperren = not value if sh...Sperre_erlauben() else None
                - .self = True if value and not sh...sperren() and not sh...sperren.prev_value() else None
        Sperre_erlauben:
            type: bool
            initial_value: False
            visu_acl: rw
            cache: yes
        automatisch_entsperren:
            type: bool
            initial_value: False
            visu_acl: rw
            cache: yes
        sperren:
            type: bool
            knx_dpt: 1
            visu_acl: rw
            cache: yes
            entsperren:
                type: bool
                visu_acl: ro
                eval: value if sh....automatisch_entsperren() else None
                eval_trigger:
                    - .....Rollladen.ist_oben
                    - .....Rollladen.ist_unten
                on_change: ..self = False
    Und hier aus der entsprechenden Item-yaml.

    Code:
        WC:
            Licht:
                Decke:
                    struct: Schalten_mit_Sperrfunktion
                    schalten:
                        knx_send: 0/5/1
                        knx_cache: 0/2/4
                        knx_listen: 0/5/1
                    sperren:
                        knx_send: 0/4/6
                        knx_reply: 0/4/6
    Sonst habe ich noch 2 Anmerkungen:

    1. Ich finde die Umsetzung mit den structs grandios, denn so vereinfacht man dich vieles, weil es einfach übersichtlicher wird. Stück für Stück setze ich alle meine Items damit um.

    2. Die Properties funktionieren, wie ich schon mal anmerkte nicht immer zuverlässig. So ist ein Ersatz der Zeile oben, durch ein property "- .self = True if value and not sh...sperren() and not sh...sperren.last_value else None" nicht möglich, weil dann ein Fehler auftritt: 'Item' object has no attribute 'last_value'. Ferner sind auch die Bezeichnungen verwirrend, weil das property last_value der Funktion prev_value() entspricht und nicht dem Property prev_value. Bei beidem würde ich mir Änderungen wünschen. Auch wenn klar ist, dass ein umbennenen von Funktionen oder Properties dazu führen müsste, dass bei einem Update auch vorhandene Items und Logiken korrigiert werden müssten. Es wäre aber auf lange Sicht konsequenter.

    #2
    Zu deinem generellen Vorhaben kann ich dir nur das Stateengine Plugin ans Herz legen. IIst am Anfang schon auch nicht leicht, aber auf smarthomeng.de hab ich Blogeinträge, die vielleicht helfen und die Doku ist sehr ausführlich (wobei wohl gerade das das Problem ist )

    Zu den Properties. Du musst last_value so abfragen: sh...sperren.property.last_value
    Also mit property! Dann funktioniert es sicher.

    Das mit dem last_value stört mich ehrlich gestanden auch extrem, aber das jetzt zu ändern ist wohl nicht realistisch. Vielleicht wenn man anfängt, die Item Funktionen (zB pre_value()) nach und nach als deprecated zu bezeichnen und so die Leute dazu bringt, Properties zu nutzen. Andererseits ist halt sh.xy() einfacher als sh.xy.property.value

    Kommentar


      #3
      Zitat von Onkelandy Beitrag anzeigen
      Zu deinem generellen Vorhaben kann ich dir nur das Stateengine Plugin ans Herz legen. IIst am Anfang schon auch nicht leicht, aber auf smarthomeng.de hab ich Blogeinträge, die vielleicht helfen und die Doku ist sehr ausführlich (wobei wohl gerade das das Problem ist )
      Das ist schon heftig. Ich habe mal gerade reingelesen. Aber das wird wohl nicht reichen. Das ist doch recht komplex. :-)

      Zitat von Onkelandy Beitrag anzeigen
      Zu den Properties. Du musst last_value so abfragen: sh...sperren.property.last_value
      Also mit property! Dann funktioniert es sicher.
      Da habe ich wohl was vergessen. :-( Dann nehme ich das natürlich oben zurück.

      Zitat von Onkelandy Beitrag anzeigen
      Das mit dem last_value stört mich ehrlich gestanden auch extrem, aber das jetzt zu ändern ist wohl nicht realistisch. Vielleicht wenn man anfängt, die Item Funktionen (zB pre_value()) nach und nach als deprecated zu bezeichnen und so die Leute dazu bringt, Properties zu nutzen. Andererseits ist halt sh.xy() einfacher als sh.xy.property.value
      Das würde nur dann gehen, wenn sämtliche Konfigurationsdateien mit einem Update auch konvertiert würden. Eine andere Lösung gibt es kaum. Ob das fehlerfrei machbar ist, muss man sehen.

      Kommentar


        #4
        Nach Jahren habe ich das Problem endlich mal gelöst. Das beschäftigte mich nämlich schon ewig. Das Licht sperre ich nun direkt am Aktor, PM würde aber auch gehen und die Sperre vollziehe ich mit der Prüfung der Dimmfunktion (also Langdruck des Tastsensors). Den aktuellen Schaltstaus erhalte ich mit knx_cache und mit knx_listen bzw. knx_send bekomme ich die Meldung vom Tastsensor bzw. sende das an den PM (externer Tastereingang)

        Hier die struct:

        Code:
        # Dimmen und ggf. Präsenzmelder (Licht) sperren
        Licht_mit_Dimm_Sperrfunktion:
            schalten:
                type: bool
                knx_dpt: 1
                enforce_updates: yes
                visu_acl: rw
                on_change: ..sperren = False if value else None
                on_update: ..Dimmwert = min(sh...Dimmwert() + 64, 255) if value and sh...Dimmwert() > 0 else None
                Alexa:
                    alexa_actions: TurnOn TurnOff
                    alexa_icon: LIGHT
                    on_update:
                        - ...sperren = not value if sh....Alexa_sperrt() else None
                        - ...schalten = value
            Dimmwert:
                type: num
                knx_dpt: 5
                visu_acl: rw
                alexa_actions: AdjustBrightness SetBrightness
                alexa_item_range: 0-255
            # value[0]: 0 = ab, 1 = auf
            # value[1]: 0 = Stopp, 1 = bewegen
            dimmen:
                type: list
                knx_dpt: 3
                visu_acl: deny
                on_change: ..sperren = True if sh...Sperre_erlauben() and not value[0] and value[1] and not sh...schalten() else None
            Sperre_erlauben:
                type: bool
                initial_value: True
                visu_acl: rw
                cache: yes
            Alexa_sperrt:
                type: bool
                initial_value: False
                visu_acl: rw
                cache: yes
            automatisch_entsperren:
                type: bool
                initial_value: True
                visu_acl: rw
                cache: yes
            sperren:
                type: bool
                knx_dpt: 1
                visu_acl: rw
                cache: yes
                on_update: .quittieren = True if value else None
                entsperren:
                    type: bool
                    visu_acl: deny
                    eval: value if sh....automatisch_entsperren() else None
                    eval_trigger: .....Nachtmodus
                    on_change: ..self = False
                quittieren:
                    type: bool
                    enforce_updates: yes
                    visu_acl: deny
                    blinken_anzahl: 7
                    blinken_puls: 3
                    blinken_pause: 3
        Und so der Code bei den Lampen:

        Code:
            Wohnen:
                Licht:
                    Decke:
                        struct: Licht_mit_Dimm_Sperrfunktion
                        schalten:
                            knx_send: 0/5/6
                            knx_cache: 0/2/6
                            knx_listen: 0/5/6
                            Alexa:
                                alexa_name: Kronleuchter Wohnen
                                alexa_alias: Kronleuchter Wohnzimmer
                                alexa_device: Kronleuchter_Wohnen
                                alexa_description: Kronleuchter Wohnen
                        Dimmwert:
                            knx_send: 0/3/6
                            knx_cache: 0/2/27
                            alexa_device: Kronleuchter_Wohnen
                        dimmen:
                            knx_listen: 0/1/6
                        sperren:
                            knx_send: 0/4/6
                            knx_reply: 0/4/6
                            quittieren:
                                blinken_ga: 0/2/6

        Kommentar


          #5
          Zitat von Cannon Beitrag anzeigen
          quittieren: type: bool enforce_updates: yes visu_acl: deny blinken_anzahl: 7 blinken_puls: 3 blinken_pause: 3
          Hallo,

          kannst Du das Quittieren noch mal kurz darstellen?
          Wie ist das realisiert?

          Danke dir.

          Kommentar


            #6
            Zitat von Sisamiwe Beitrag anzeigen
            kannst Du das Quittieren noch mal kurz darstellen?
            Wie ist das realisiert?
            Das ist eine Blinkfunktion. In Form einer Logik und hier wird dann noch das Attribut blinken_ga getriggert. Da hat mir hier im Forum jemand geholfen. Ich habe das noch um eine Dimmmöglichkeit erwweitert. Es gibt ja derzeit leider keine direkte Möglichkeit ein Item blinken zu lassen.

            Code:
            #!/usr/bin/env python
            #
            # Abstrakte blink-Logik, blinkt wenn das Item <> 0 ist - ist somit für num und bool items geeignet
            #
            # blinken_ga (string, verpflichtend) ist das watch-Attribut, hat als argument die blink-GA
            # blinken_not (bool, default false) lässt blinken, wenn das Item 0 ist
            # blinken_anzahl (num, default 7, max 100) ist die Anzahl der Blinkvorgsenge
            # blinken_puls (num, default 10, in Sekunden/10) ist die Laenge des "an"-blinkens
            # blinken_pause (num, default 10, in Sekunden/10) ist die Laenge des "aus"-blinkens
            # blinken_invert (bool, default false) invertiert Puls/Pause (für negative Anzeige)
            # blinken_final (string, Item, default leer) setzt den Zustand des Items als letzten Blinkwert
            # blinken_startpause (num, default 0, in Sekunden/10) wie lange wird gewartet, bevor das Blinken anfängt
            # blinken_dimmwert_ein (num, default None) anstatt ein/aus wird der Dimmwert gesetzt, Achtung Gruppenadresse muss für Dimmwert sein
            # blinken_dimmwert_aus (num, default 0) anstatt ein/aus wird der Dimmwert gesetzt
            #logger.info("blinken")
            #print(trigger)
            # logik nur, wenn von Item getriggert
            if trigger['by'] == 'Item':
                lItem = sh.return_item(trigger['source'])
                lGA = lItem.conf['blinken_ga']
                lAnzahl = int(lItem.conf['blinken_anzahl']) if 'blinken_anzahl' in lItem.conf else 7
                lPuls = int(lItem.conf['blinken_puls']) if 'blinken_puls' in lItem.conf else 10
                lPause = int(lItem.conf['blinken_pause']) if 'blinken_pause' in lItem.conf else 10
                lStartPause = int(lItem.conf['blinken_startpause']) if 'blinken_startpause' in lItem.conf else 0
                ldimmwert_ein = int(lItem.conf['blinken_dimmwert_ein']) if 'blinken_dimmwert_ein' in lItem.conf else None
                ldimmwert_aus = int(lItem.conf['blinken_dimmwert_aus']) if 'blinken_dimmwert_aus' in lItem.conf else 0
                lFinal = lItem.conf['blinken_final'] if 'blinken_final' in lItem.conf else ""
                lInvert = 'blinken_invert' in lItem.conf
                lNot = 'blinken_not' in lItem.conf
                time.sleep(lStartPause / 10.0)
                #logger.info("Blinken {3} mal auf {0} mit ({1}/{2}), invertiert: {4}".format(lGA, lPuls, lPause, lAnzahl, lInvert))
                lContinue = (lItem() > 0) != lNot
                while lContinue and lAnzahl > 0:
                    lAnzahl = lAnzahl - 1
                    logger.debug("Blinken: GA {0} => {1}".format(lGA,int(not lInvert)))
                    if ldimmwert_ein == None:
                        sh.knx.groupwrite(lGA, not lInvert, '1')
                    else:
                        if lInvert:
                            sh.knx.groupwrite(lGA, ldimmwert_aus, '5')
                        else:
                            sh.knx.groupwrite(lGA, ldimmwert_ein, '5')
                    time.sleep(lPuls/10.0)
                    logger.debug("Blinken: GA {0} => {1}".format(lGA,int(lInvert)))
                    if ldimmwert_ein == None:
                        sh.knx.groupwrite(lGA, lInvert, '1')
                    else:
                        if not lInvert:
                            sh.knx.groupwrite(lGA, ldimmwert_aus, '5')
                        else:
                            sh.knx.groupwrite(lGA, ldimmwert_ein, '5')
                    lContinue = (lItem() > 0) != lNot
                    if lContinue: time.sleep(lPause / 10.0)
                if lFinal != "":
                    lValue = sh.return_item(lFinal)()
                    logger.debug("Blinken final: GA {0} => {1}".format(lGA,lValue))
                    sh.knx.groupwrite(lGA, lValue, '1')
            Jetzt, wo ich das gerade poste, sehe ich das man das noch vereinfachen könnte, indem man statt dimmwert_an und aus einfach einen generellen Wet für an und aus festlegt, dann braucht man da keinen Unterschied zu machen.

            Kommentar

            Lädt...
            X