Ankündigung

Einklappen
Keine Ankündigung bisher.

Plugin Treppenlichtautomat

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

    Plugin Treppenlichtautomat

    Hallo zusammen,

    da mir der Parameter "autotimer" nicht ausgereicht hat, hab ich die Herausforderung angenommen, und mich an meinem ersten Plugin für Smarthome.py versucht.
    Herausgekommen ist ein Plugin für einen Treppenlichtautomat (TLA) mit zahlreichen Features. So lässt sich z.B. eine Einschaltverzögerung einstellen, oder auch eine Vorwarnung, bevor das Licht wieder ausgeht. Dauerlicht und Sperrfunktion sind ebenfalls realisiert, usw. Ich habe im Readme alles (hoffentlich verständlich) beschrieben.

    Vielleicht kann es außer mir ja sonst noch jemand brauchen. Über Feedback zu Fehlern, Korrekturen und Verbesserungwünsche freue ich mich natürlich.
    Bitte seid nachsichtig, es sind meine ersten Schritte in Python. Deswegen bin ich auch offen für Feedback, falls ich vom Programmieren her was unglücklich gelöst hab und es ein eleganteres Vorgehen gibt.

    Ich habe das Plugin bei mir erfolgreich im Echteinsatz, trotzdem ist es natürlich noch eine Beta-Version.

    P.S.: Leider kann ich aktuell kein Zip-File als Anhang hochladen. Ich vermute, das hängt mit der neuen Forumssoftware zusammen. Deswegen poste ich den Code vorerst direkt hier.

    Gruß
    Markus


    __init__.py:
    Code:
    #!/usr/bin/env python3
    # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
    #########################################################################
    # TLA - Treppenlichtautomat, Plugin für Smarthome.py
    # Copyright 2015 Markus Grossmann (m_grossmann@gmx.de)
    # Version 0.2 (Beta)
    #########################################################################
    #  This file is part of SmartHome.py.    http://mknx.github.io/smarthome/
    #
    #  SmartHome.py is free software: you can redistribute it and/or modify
    #  it under the terms of the GNU General Public License as published by
    #  the Free Software Foundation, either version 3 of the License, or
    #  (at your option) any later version.
    #
    #  SmartHome.py is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with SmartHome.py. If not, see <http://www.gnu.org/licenses/>.
    #########################################################################
    #
    
    
    import logging
    import datetime
    
    logger = logging.getLogger('')
    
    
    class TLA():
        def set_status(self, item, status):
            # Status
            #  0 = Init
            # 10 = Dauer aus
            # 11 = Dauer ein
            # 20 = Licht aus, Einschaltverzoergerung
            # 21 = Licht ein, TLA-Zeit laeuft
            # 30 = Licht aus, Vorwarnung
            # 31 = Licht ein, Vorwarnung
            # 41 = Licht ein, Sperre
            logger.debug("TLA-Plugin: set-status, alt: {0}, neu: {1}".format(item.tla_status,status))
            item.tla_status = status
            if status in [10, 20, 30]:
                item(False)
                if hasattr(item,'tla_visu'):
                    item.tla_visu(False)
            elif status in [11, 21, 31, 41]:
                item(True)
                if hasattr(item,'tla_visu'):
                    item.tla_visu(True)
        
        def remove_timer(self, item):
            logger.debug("TLA-Plugin: remove_timer")
            self._sh.scheduler.remove(item.id() + '-Timer')
            
        def start_timer(self, item, dauer, funktion):
            logger.debug("TLA-Plugin: start_timer, dauer: {0}, funktion: {1}".format(dauer, funktion))
            next = self._sh.now() + datetime.timedelta(seconds=dauer)
            self._sh.scheduler.add(item.id() + '-Timer', funktion, prio=3, value={'item': item}, next=next)
    
        def start_tla(self, item, einschaltverzoegerung = 0, remove = False):
            logger.debug("TLA-Plugin: start_tla: evz: {0}, remove:{1}".format(einschaltverzoegerung, remove))
            if remove:
                self.remove_timer(item)
            
            if int(item.conf['tla_helligkeit_max']) > 0 and int(item.conf['tla_helligkeit']) > int(item.conf['tla_helligkeit_max']):
                logger.debug("TLA_Plugin: start_tla: Helligkeitsschwelle ueberschritten! ist: {0}, max: {1}".format(item.conf['tla_helligkeit'], item.conf['tla_helligkeit_max']))
                self.set_status(item, 10)
                return
    
            if einschaltverzoegerung == 0:
                self.set_status(item, 21)
                self.start_timer(item, int(item.conf['tla']), self.stop_tla)
            else:
                self.set_status(item, 20)
                self.start_timer(item, int(item.conf['tla_einschaltverzoegerung']), self.start_tla)
    
        def stop_tla(self, item):
            logger.debug("TLA-Plugin: stop_tla: {0}".format(item))
            if int(item.conf['tla_anzahl_warnungen']) == 0:
                self.set_status(item, 10)
            else:
                if item.tla_status == 21:
                    item.tla_warnungen_zaehler = 0
                if item.tla_status in [21, 31]:
                    item.tla_warnungen_zaehler += 1
                    if item.tla_warnungen_zaehler > int(item.conf['tla_anzahl_warnungen']):
                        self.set_status(item, 10)
                    else:
                        self.set_status(item, 30)
                        self.start_timer(item, int(item.conf['tla_warndauer']), self.stop_tla)
                else:
                    self.set_status(item, 31)
                    self.start_timer(item, int(item.conf['tla_vorwarnzeit']), self.stop_tla)
        
        def set_default(self, item, parameter, wert):
            if parameter not in item.conf:
                item.conf[parameter] = wert
        
        def __init__(self, smarthome):
            logger.info('Init TLA-Plugin')
            self._sh = smarthome
    
        def run(self):
            self.alive = True
            # if you want to create child threads, do not make them daemon = True!
            # They will not shutdown properly. (It's a python bug)
    
        def stop(self):
            self.alive = False
    
        def parse_item(self, item):
            if 'tla' in item.conf:
                logger.debug("TLA-Plugin: parse item: {0}".format(item))
                logger.debug("TLA-Plugin: item.conf: {0}".format(item.conf))
    
                value = item.conf['tla']
                if value.isdigit():
                    item.tla_status = 0
                    item.tla_gesperrt = False
    
                    self.set_default(item, 'tla_einschaltverzoegerung', 0)
                    self.set_default(item, 'tla_sperren', 0)
                    self.set_default(item, 'tla_entsperren', 0)
                    self.set_default(item, 'tla_verlaengern', 1)
                    self.set_default(item, 'tla_vorwarnzeit', 60)
                    self.set_default(item, 'tla_warndauer', 1)
                    self.set_default(item, 'tla_anzahl_warnungen', 0)
                    self.set_default(item, 'tla_helligkeit_max', 0)
                    self.set_default(item, 'tla_helligkeit', 10000)
                    logger.debug("TLA-Plugin: item.conf: {0}".format(item.conf))
    
                if value == 'dauer':
                    return self.tla_dauer
                if value == 'trigger':
                    return self.tla_trigger
                if value == 'sperre':
                    return self.tla_sperre
                if value == 'helligkeit':
                    return self.tla_helligkeit
                if value == 'visu':
                    tla_item = item.return_parent()
                    tla_item.tla_visu = item
                    return self.tla_visu
    
                #return self.update_item
                return None
            else:
                return None
    
        def update_item(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: update item: {0}".format(item.id()))
    #        if caller != 'plugin':
    #            logger.info("update item: {0}".format(item.id()))
    
        def tla_trigger(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: tla_trigger: {0}".format(item._value))
            tla_item = item.return_parent()
            logger.debug("TLA-Plugin: item.conf: {0}".format(tla_item.conf))
            if item._value and not tla_item.tla_gesperrt:
                if tla_item.tla_status in [0, 10]:
                    self.start_tla(tla_item, einschaltverzoegerung = int(tla_item.conf['tla_einschaltverzoegerung']))
                elif (tla_item.tla_status == 21 and int(tla_item.conf['tla_verlaengern']) == 1) or tla_item.tla_status in [30, 31]:
                    self.start_tla(tla_item, remove=True)
    
        def tla_sperre(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: tla_sperre: {0}".format(item._value))
            tla_item = item.return_parent()
            if item._value:
                tla_item.tla_gesperrt = True;
                if tla_item.tla_status in [20, 21, 30, 31]:
                    self.remove_timer(tla_item)
                if tla_item.tla_status != 11:
                    if int(tla_item.conf['tla_sperren']) == -1:   # -1 = Licht aus (außer bei Dauerlicht)
                        self.set_status(tla_item, 10)
                    elif int(tla_item.conf['tla_sperren']) == 1:  # 1 = Licht ein
                        self.set_status(tla_item, 41)
                    else:                                         # 0  = unverändert, sprich: wenn Licht über TLA an war, bleibt es an
                        if tla_item.tla_status in [21,31]:
                            self.set_status(tla_item,41)
                        else:
                            self.set_status(tla_item,10)
            else:
                tla_item.tla_gesperrt = False
                if int(tla_item.conf['tla_entsperren']) == 1:  # 1  = Licht ein, Treppenlichtzeit wird aktiviert (außer bei Dauerlicht)
                    if tla_item.tla_status == 10:
                        self.start_tla(tla_item, einschaltverzoegerung = int(tla_item.conf['tla_einschaltverzoegerung']))
                    elif tla_item.tla_status == 41:
                        self.start_tla(tla_item)
                elif int(tla_item.conf['tla_entsperren']) == -1:  # -1 = Licht aus (außer bei Dauerlicht)
                    if tla_item.tla_status != 11:
                        self.set_status(tla_item,10)
                elif tla_item.tla_status == 41:                       # 0  = unverändert. Wenn Licht über Sperre an war (nicht Dauerlicht), wird Treppenlichtzeit aktiviert
                        self.start_tla(tla_item)
    
        def tla_dauer(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: tla_dauer: {0}".format(item._value))
            tla_item = item.return_parent()
            if item._value:
                if tla_item.tla_status in [20, 21, 30, 31]:
                    self.remove_timer(tla_item)
                self.set_status(tla_item,11)
            else:
                self.set_status(tla_item,10)
    
        def tla_helligkeit(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: tla_helligkeit: {0}".format(item._value))
            tla_item = item.return_parent()
            tla_item.conf['tla_helligkeit'] = item._value
            
        def tla_visu(self, item, caller=None, source=None, dest=None):
            logger.debug("TLA-Plugin: tla_visu: {0}".format(item._value))
            if caller != 'Logic':
                tla_item = item.return_parent()
                if item._value:
                    self.tla_trigger(item)
                    if not tla_item._value:
                        item(False)
                else:
                    if tla_item.tla_status not in [11, 41]:
                        if tla_item.tla_status in [20, 21, 30, 31]:
                            self.remove_timer(tla_item)
                        self.set_status(tla_item,10)
                    if tla_item._value:
                        item(True)
    
    if __name__ == '__main__':
       logging.basicConfig(level=logging.DEBUG)
       myplugin = TLA()
       myplugin.run()

    README.md:
    Code:
    #########################################################################
    # TLA - Treppenlichtautomat, Plugin für Smarthome.py
    # Copyright 2015 Markus Grossmann (m_grossmann@gmx.de)
    # Version 0.2 (Beta)
    #########################################################################
    
    ## plugin.conf
    
    <pre>
    [tla]
       class_name = TLA
       class_path = plugins.tla
    </pre>
    
    
    ## items.conf
    
    # Um das TLA-Plugin fuer ein item zu aktivieren, muss das Item vom Typ bool sein,
    # und der Parameter tla = <dauer> gesetzt werden. Mit <dauer> wird die Dauer
    # für den Treppenlichtautomat (TLA ) in Sekunden angegeben.
    type = bool
    tla = 300
    
    # Einschaltverzögerung in Sekunden, default = 0
    tla_einschaltverzoergerung = 0
    
    # Verhalten bei Sperren
    # Während Anliegen des Sperrobjektes wird keine Treppenlichtfunktion
    # ausgeführt. Was soll beim Setzen des Sperrobjektes passieren?
    # 1  = Licht ein
    # -1 = Licht aus (außer bei Dauerlicht)
    # 0  = unverändert, sprich: wenn Licht über TLA an war, bleibt es an (default)
    tla_sperren = 0
    
    # Verhalten bei Entsperren
    # Nach Rücknahme des Sperrobjektes wird die Treppenlichtfunktion
    # wieder aktiviert. Was soll beim Zurücketzen des Sperrobjektes passieren?
    # 1  = Licht ein, Treppenlichtzeit wird aktiviert (außer bei Dauerlicht,
    #      und nur, wenn die Helligkeitsschwelle unterschritten ist).
    # -1 = Licht aus (außer bei Dauerlicht)
    # 0  = unverändert. Wenn Licht über Sperre an war (nicht Dauerlicht), wird Treppenlichtzeit aktiviert (default)
    tla_entsperren = 0
    
    # Kann durch erneutes Senden des Trigger-Items waehrend der aktiven Zeit
    # die Zeit verlaengert werden? (1 = ja, 0 = nein), default = 1
    # Hinweis: Ein TLA-Signal wärend der Vorwarnung startet den TLA immer neu, unabhängig vom Wert "verlaengern"
    tla_verlaengern = 1
    
    # Soll am Ende des TLA vorgewarnt werden? Das bedeutet: Das Licht blink ein- oder mehrmals, bevor es endgültig ausgeht.
    # Wenn ja, muss die Anzahl der Warnungen angegeben werden. (default = 0)
    # Über die Warndauer wird festgelegt, wie lange das Licht aus bleibt (default = 1 Sekunde, nur Ganzzahl!)
    # Die Vorwarnzeit gibt an, wie lange nach der Warnung das Licht nochmal anbleibt
    # (Bis zur Naechsten Warnung, bzw. bis das Licht ausgeschaltet wird, default = 60 Sekunden)
    # Die Gesamtzeit des TLA ergibt sich folgendermaßen:
    # tla + tla_anzahl_warnungen * (tla_warndauer + tla_vorwarnzeit)
    tla_anzahl_warnungen = 2
    tla_warndauer = 1
    tla_vorwarnzeit = 5
    
    # Es kann ein Helligkeitswert angegeben werden, unter dem der TLA aktiv wird.
    # Ist der Wert = 0 (default), so ist der TLA unabhängig von der Helligkeit aktiv.
    tla_helligkeit_max = 500
    
    # Zusätzlich ist eines de beiden Sub-Items mit dem Parameter tla = trigger
    # oder tla = visu notwendig.
    
    # Mit dem Sub-Item mit dem Parameter tla = trigger kann der TLA ausgelöst werden.
    # Das Item ist gedacht, um z.B. mit dem Kommunikationsobjekt eines Bewegungsmelders
    # verbunden zu werden. Es wird nur der Wert 1 bzw. True ausgewertet.
    # Es empfielt sich, zusätzlich den Parameter enforce_updates = true zu setzen,
    # falls z.B. ein Bewegungsmelder mehrmals 1 schickt, ohne zwischendurch 0 zu schicken,
    # und damit die Zeit verlaengert werden soll.
    tla = trigger
    enforce_updates = true
    
    # Das Sub-Item mit tla = visu wird speziell für die Visualisierung oder für Tastsensoren
    # bereitgestellt. Mit diesem kann der TLA getriggert werden (Flanke 0-1),
    # und das Licht ausgeschaltet werden (Flanke 1-0). Sperre und Dauerlicht
    # haben Vorrang.
    # Das Sub-Item wird zudem automatisch aktualisiert, wenn das Licht geschaltet wird,
    # d.h., in der Visu oder mit einer Status-LED an einem Tastsensor kann Zustand angezeigt werden.
    tla = visu
    
    # Das Sub-Item mit tla = dauer ist optional. Mit diesem kann das Licht
    # zwangsweise dauerhaft ein- und ausgeschaltet werden.
    tla = dauer
    
    # Das Sub-Item mit tla = sperre ist optional. Mit diesem kann der TLA
    # gesperrt werden. Das Verhalten der Sperre ist abhaengig von den oben
    # gesetzten Parametern
    tla = sperre
    
    # Ueber das Sub-Item mit tla = helligkeit kann ein Helligkeitswert an den
    # TLA gegeben werden
    tla = helligkeit
    
    
    
    
    ### Beispiel
    
    Please provide an item configuration with every attribute and usefull settings.
    
    <pre>
    [flur]
        [[licht]]
            type = bool
            visu_acl = ro
            tla = 300
            tla_helligkeit_max = 500
            knx_dpt = 1
            knx_send = 1/1/1
            [[[dauer]]]
                tla = dauer
                type = bool
                visu_acl = rw
                knx_dpt = 1
                knx_cache = 1/2/1
            [[[trigger]]]
                tla = trigger
                type = bool
                visu_acl = rw
                enforce_updates = true
                knx_dpt = 1
                knx_cache = 1/4/1
            [[[sperre]]]
                tla = sperre
                type = bool
                visu_acl = rw
                knx_dpt = 1
                knx_cache = 1/7/1
            [[[helligkeit]]]
                tla = helligkeit
                type = num
                visu_acl = ro
                knx_dpt = 9
                knx_cache = 7/1/5
            [[[visu]]]
                type = bool
                tla = visu
                visu_acl = rw
    
    </pre>

    #2
    Hallo Markus,

    danke für das Plugin. Ich hoffe es finden auch anderen Anwender hilfreich.

    Bis bald

    Marcus

    Kommentar

    Lädt...
    X