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:
README.md:
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.

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>
Kommentar