Funktionen und Klassen in Logiken

Funktionen in Logiken

Bei der Nutzung von Funktionen in Logiken ist eine Besonderheit zu beachten: Eine Logik verhält sich nicht wie ein Python Modul!

Bemerkung

Bis zu SmartHomeNG v1.9.2 gilt:

Eine Logik verhält sich nicht wie ein Python Modul! Variablen und Funktionen die auf Ebene der Logik definiert werden, sind keine globalen Objekte. Sie stehen in Funktionen die innerhalb der Logik definiert werden nicht zur Verfügung. Daher müssen Variablen und Funktionen die innerhalb von Funktionen genutzt werden, der Funktion explizit bekannt gemacht werden.

Sollen in der Logik weitere Python Module genutzt werden, so muss der import der Moduls innerhalb der Funktion erfolgen, die eine Funktion aus dem zu importierenden Python Modul nutzt.

Wichtig

Ab dem nachfolgenden Release v1.9.3 wurde ein global Environment für Logiken eingeführt

Ab diesem Release stehen Variablen, die in der Hauptroutine der Logik definiert wurden auch in Funktionen innerhalb der Logik zur Verfügung. Das gleiche gilt für Module, die in der Hauptroutine der Logik importiert wurden.

Daher ist es auch nicht mehr notwendig, das logic Objekt als Parameter an die Funktionen innerhalb einer Logik zu übergeben.

Dafür müssen Funktionen und Variablen der Funktion als Parameter übergeben werden. Das kann geschehen, indem die Übergabe für jede Variable/Funktion einzeln erfolgt oder sie können in einem Objekt übergeben werden (was die zu bevorzugende Methode ist.

Dazu kann das Objekt logic genutzt werden, welches SmartHomeNG zur Verfüfung stellt um Variablen zu implementieren, die den Lauf der Logik „überleben“ und beim nächsten Lauf dieser Logik wieder zur Verfügung stehen. Das logic Objekt ist privat. Das bedeutet, jede Logik hat ihr eigenes logic Objekt.

Funktionen müssen dazu in der Definition den zusätzlichen Parameter logic enthalten. Das sollte zur besseren Handhabung der letzte Parameter sein. Da dieser Parameter innerhalb der Logik immer mit dem selben Wert übergeben wird, kann der Wert auch gleich als Standard-Wert in der Funktionsdefinition mit angegeben werden. Dann braucht er in den Aufrufen der Funktion nicht angegeben zu werden.

Das folgende Beispiel verdeutlicht das Vorgehen:

bis SmartHomeNG v1.9.2

# Variablen, die in Funktionen genutzt werden sollen, müssen dem logic Objekt zugewiesen werden
logic.sh = sh
logic.myvar1 = 5
logic.myvar2 = False

# Funktionen definieren und anschließend dem logic Objekt zuweisen
def func1(wert, logic=logic):
    logic.logger.warning("Funktion 1: wert = {}".format(wert))
logic.func1 = func1

def func2(logic=logic):
    logic.logger.warning("Funktion 2")
    logic.func1(2)
logic.func2 = func2


# Main Routine der Logik
logic.func1(1)
logic.func2()

Um aus Funktionen heraus auf das sh Objekt zugreifen zu können, sollte auch dieses (wie im obigen Beispiel) als Variable im logic Objekt abgelegt werden.

ab SmartHomeNG v1.9.3

In neueren Versionen von SmartHomeNG kann der Syntax deutlich vereinfacht werden. Der alte Syntax ist jedoch weiterhin gültig.

# Funktionen definieren und anschließend dem logic Objekt zuweisen
def func1(wert):
    logger.warning("Funktion 1: wert = {}".format(wert))

def func2(logic=logic):
    logger.warning("Funktion 2")
    func1(2)


# Main Routine der Logik
func1(1)
func2()

Klassen in Logiken

In Logiken können auch Klassen definiert werden. Damit diese Klassen in Funktionen zur Verfügung stehen, muss auch hier (wie bei Funktionen) die Klasse dem Logik Objekt zugewiesen werden (letzte Zeile im folgenden Beispiel):

bis SmartHomeNG v1.9.2

class triggervalue():

    def __init__(self, init_value=None, trigger_item=None, logic=None):
        self.trigger_item = trigger_item
        self.value = init_value
        self.changed = False
        self._last_value = init_value
        if self.trigger_item is not None:
            self.value = logic.items.return_item(trigger_item)()
            self.changed = (logic.trigger_dict['source'] == trigger_item)
            self._last_value = None

    def set(self, newvalue):
        if self.trigger_item is None:
            self._last_value = self.value
            self.value = newvalue
            self.changed = self.value != self._last_value
            return self.changed
        return self.changed
logic.triggervalue = triggervalue

Wenn in einer Klasse auf Elemente des logic Objektes zugegriffen werden soll (wie in dem obigen Beispiel), muss logic beim Erstellen einer Instanz mit übergeben werden:

logic.freigabe_sued = logic.triggervalue(trigger_item='beschattung.beschattungsautomatik.sued', logic=logic)

ab SmartHomeNG v1.9.3

In neueren Versionen von SmartHomeNG kann der Syntax vereinfacht werden. Der alte Syntax ist jedoch weiterhin gültig.

class triggervalue():

    def __init__(self, init_value=None, trigger_item=None):
        self.trigger_item = trigger_item
        self.value = init_value
        self.changed = False
        self._last_value = init_value
        if self.trigger_item is not None:
            self.value = logic.items.return_item(trigger_item)()
            self.changed = (logic.trigger_dict['source'] == trigger_item)
            self._last_value = None

    def set(self, newvalue):
        if self.trigger_item is None:
            self._last_value = self.value
            self.value = newvalue
            self.changed = self.value != self._last_value
            return self.changed
        return self.changed

Wenn in einer Klasse auf Elemente des logic Objektes zugegriffen werden soll (wie in dem obigen Beispiel), muss logic beim Erstellen einer Instanz mit übergeben werden:

freigabe_sued = triggervalue(trigger_item='beschattung.beschattungsautomatik.sued')

Zu beachten ist hierbei, dass das Weglassen der Zeile

logic.triggervalue = triggervalue

und das Ansprechen der Objektes ohne den Präfix logic. dazu führt, dass das Objekt nur während des Laufed der Logik existiert. Wird hingegen das Objekt im logic Objekt abgelegt, existert das Objekt mis zum Neustart von SmartHomeNG (Siehe dazu auch Persistente Variablen).