Funktionsbaustein: Benutzerdefinierter Code¶
Der Funktionsbaustein Benutzerdefinierter Code ermöglicht es, eigene Python-Logik innerhalb eines Wetterrelais-Programms auszuführen.
Damit lassen sich beispielsweise individuelle Berechnungen, Filter, Zustände, Zeitfunktionen, JSON-Verarbeitung und HTTP-Anfragen umsetzen.
Der Code wird dabei nicht als uneingeschränktes Python-Programm ausgeführt. Es steht bewusst nur ein begrenzter und kontrollierter Funktionsumfang zur Verfügung. Dadurch kann eigener Code verwendet werden, ohne direkten Zugriff auf Dateien, Hardware, Relais, Netzwerk-Sockets oder interne Programmteile des Wetterrelais zu erhalten.
Hinweis: Der Funktionsbaustein eignet sich zur Erweiterung der Programmlogik. Er ist kein Ersatz für eine vollständige Python- oder MicroPython-Umgebung.
Funktionsbaustein einfügen¶
Der Code-Baustein befindet sich im Programmeditor in der Toolbox in der Gruppe Benutzerdefiniert unter der Bezeichnung Code.
Er kann auf zwei Arten eingefügt werden:
- Code in der Toolbox anklicken. Der Baustein wird in der Mitte des sichtbaren Arbeitsbereichs eingefügt.
- Code aus der Toolbox an die gewünschte Position auf der Arbeitsfläche ziehen.
Ein neu eingefügter Baustein erhält automatisch einen Namen wie Code 1, Code 2 oder Code 3. Dieser Name kann in den Eigenschaften geändert werden.
Oberhalb des Bausteins wird zusätzlich die feste Operatornummer angezeigt, beispielsweise N4. Sie dient zur eindeutigen Zuordnung des Funktionsbausteins und ist unabhängig vom frei vergebenen Namen.
Ein- und Ausgang festlegen¶
Der Funktionsbaustein besitzt einen frei konfigurierbaren Ausgang und optional einen Eingang.
Die Typen werden in den Eigenschaften des Bausteins über Eingangstyp und Ausgangstyp festgelegt.
Eingangstyp¶
| Einstellung | Bedeutung |
|---|---|
| Kein Eingang | Der Baustein arbeitet selbstständig und benötigt keinen Wert von einem anderen Funktionsbaustein. |
| Logik | Der Eingang verarbeitet True oder False. |
| Wert | Der Eingang verarbeitet einen einzelnen Zahlenwert. |
| Daten | Der Eingang verarbeitet mehrere zusammengehörige numerische Werte. |
Bei Kein Eingang wird auf der linken Seite des Bausteins kein Anschluss angezeigt.
Bei Logik, Wert oder Daten erscheint der entsprechende Eingang und kann mit einem anderen Funktionsbaustein verbunden werden.
Ausgangstyp¶
| Einstellung | Rückgabewert |
|---|---|
| Logik | True oder False |
| Wert | Ein einzelner Zahlenwert, beispielsweise 12, 25.5 oder -4 |
| Daten | Eine numerische Datenreihe oder eine verschachtelte numerische Datenstruktur |
Der im Handler mit return zurückgegebene Wert muss zum gewählten Ausgangstyp passen.
Beispiel für Logik:
Beispiel für Wert:
Beispiel für Daten:
True und False werden dabei ausschließlich als logische Werte behandelt und nicht als Zahlen.
Wird der Eingangs- oder Ausgangstyp nachträglich geändert, können bestehende Verbindungen entfernt werden, wenn sie mit dem neuen Typ nicht mehr zulässig sind. Nach einer Typänderung sollten deshalb die Verbindungen des Bausteins geprüft werden.
Die drei Codebereiche¶
Jeder Code-Baustein besitzt drei getrennte Codebereiche:
- Init-Code
- Update-Code
- Handler-Code
Die Aufteilung ist notwendig, weil diese Bereiche zu unterschiedlichen Zeitpunkten ausgeführt werden.
| Bereich | Ausführung | Typische Aufgabe |
|---|---|---|
| Init-Code | Einmal beim Start bzw. Laden des Programms | Dauerhafte Variablen und Einstellungen anlegen |
| Update-Code | Einmal zu Beginn jedes Programmzyklus | Zyklusbezogene Vorbereitungen durchführen |
| Handler-Code | Nach dem Update und bei Bedarf erneut innerhalb des Zyklus | Ausgangswert berechnen |
Init-Code¶
Der Init-Code wird einmal ausgeführt, wenn der Code-Baustein beim Laden des Programms angelegt wird.
Er eignet sich für:
- Startwerte
- Zähler
- feste Einstellungen
- URLs
- Grenzwerte
- Listen oder Dictionaries, die über mehrere Programmzyklen erhalten bleiben sollen
Beispiel:
Variablen, die später im Update- oder Handler-Code benötigt werden, sollten als Eigenschaft von self angelegt werden:
Später kann darauf wieder zugegriffen werden:
Kein Eingang im Init-Code¶
Der Init-Code darf nicht auf den Eingang des Funktionsbausteins zugreifen.
Beim Programmstart ist nicht sichergestellt, dass ein vorgeschalteter Funktionsbaustein bereits einen gültigen Ausgang berechnet hat. Die Verarbeitung von Eingangsdaten gehört deshalb in den Handler-Code.
Lebensdauer von self-Variablen¶
Mit self angelegte Variablen bleiben über mehrere Programmzyklen erhalten:
Sie bleiben erhalten, solange der Funktionsbaustein existiert. Sie werden jedoch nicht dauerhaft im Gerät gespeichert.
Nach einem Neustart des Wetterrelais oder einem erneuten Laden des Programms wird der Init-Code erneut ausgeführt und die Variablen werden neu angelegt.
Update-Code¶
Der Update-Code wird einmal zu Beginn jedes Programmzyklus ausgeführt.
Er eignet sich für Arbeiten, die genau einmal pro Zyklus erfolgen sollen, beispielsweise:
- Zähler erhöhen
- Merker verändern
- zyklusbezogene Werte vorbereiten
- Zustände zurücksetzen
- einmalige Berechnungen durchführen
Beispiel:
Nach dem Update-Code wird der Handler automatisch ausgeführt.
Für viele Anwendungen wird deshalb kein eigener Update-Code benötigt. In diesem Fall genügt:
Wichtig:
handler()darf im eigenen Code nicht direkt aufgerufen werden. Der Programmeditor übernimmt den Handler-Aufruf automatisch.
Handler-Code¶
Der Handler-Code berechnet den eigentlichen Ausgang des Funktionsbausteins.
Ein Handler kann innerhalb eines einzigen Programmzyklus mehrfach ausgeführt werden. Das ist erforderlich, weil ein vorgeschalteter Funktionsbaustein seinen Ausgang möglicherweise noch nicht berechnet hat.
Eingang verwenden¶
Der Wert des Eingangs steht im Handler über die Variable input zur Verfügung.
Beispiel:
Solange kein Eingangswert vorliegt, wird None zurückgegeben.
Bedeutung von return None¶
bedeutet:
Der Funktionsbaustein kann seinen Ausgang im aktuellen Moment noch nicht bestimmen.
Der Handler kann danach innerhalb desselben Programmzyklus erneut ausgeführt werden.
Sobald ein Wert ungleich None zurückgegeben wurde, gilt der Ausgang des Bausteins für den aktuellen Programmzyklus als berechnet.
None ist dabei weder die Zahl 0 noch der logische Zustand False.
Ausgang zurückgeben¶
Der Benutzer gibt ausschließlich den eigentlichen Wert zurück.
Beispiel:
Es muss kein zusätzliches Datenobjekt oder eine Typinformation erzeugt werden. Der Programmeditor ordnet dem Rückgabewert automatisch den eingestellten Ausgangstyp zu.
Baustein ohne Eingang¶
Bei Kein Eingang kann der Handler seinen Wert selbstständig bestimmen.
Typische Anwendungen sind:
- feste Werte
- eigene Berechnungen
- Zähler
- Zeitfunktionen
- HTTP-Abfragen
- JSON-Auswertungen
- eigene Zustände über mehrere Programmzyklen
Ein Baustein ohne Eingang sollte normalerweise nicht dauerhaft None zurückgeben, da sein Ausgang sonst nicht berechnet werden kann.
Dauerhafte und zyklusbezogene Variablen¶
Dauerhafte Variablen¶
Variablen mit self bleiben über mehrere Programmzyklen erhalten:
Ein einfacher Zähler kann beispielsweise so aufgebaut werden.
Init-Code¶
Update-Code¶
Handler-Code¶
Der Ausgang liefert anschließend nacheinander:
Die Erhöhung erfolgt bewusst im Update-Code. Würde der Zähler im Handler verändert, könnte die Änderung innerhalb eines Programmzyklus mehrfach ausgeführt werden.
Zykluslokale Variablen¶
Variablen ohne self, die im Update- oder Handler-Code angelegt werden, gelten nur für den aktuellen Programmzyklus.
Beispiel:
Sie können bei mehreren Handler-Aufrufen innerhalb desselben Zyklus erhalten bleiben, werden jedoch beim nächsten Programmzyklus entfernt.
Eigene Funktionen¶
Eigene Funktionen sind innerhalb des Custom Codes erlaubt.
Beispiel:
def scale_percent(value):
return int(value * 65535 / 100)
if input == None:
return None
else:
return scale_percent(input)
Dabei gelten folgende Regeln:
- Funktionen müssen auf oberster Ebene des jeweiligen Codebereichs definiert werden.
- Eine Funktion ist nur in dem Codebereich verfügbar, in dem sie definiert wurde.
- Eine Funktion aus dem Init-Code steht deshalb nicht automatisch im Handler-Code zur Verfügung.
- Pro Codebereich sind maximal 8 Funktionen erlaubt.
- Eine Funktion darf maximal 8 Parameter besitzen.
- Positionsargumente und benannte Argumente sind erlaubt.
- Rekursion ist nicht erlaubt.
- Die maximale verschachtelte Funktionsaufruftiefe beträgt 4.
- Verschachtelte Funktionen sind nicht erlaubt.
- Default-Parameter sind nicht erlaubt.
- Typannotationen sind nicht erlaubt.
*argsund**kwargssind nicht erlaubt.- Dekoratoren sind nicht erlaubt.
Der Handler-Code selbst muss einen erreichbaren return enthalten. Ein return, das ausschließlich innerhalb einer Hilfsfunktion steht, reicht nicht aus.
Unterstützte Python-Syntax¶
Der Custom Code unterstützt bewusst nur einen ausgewählten Teil von Python.
Zuweisungen¶
value = 10
self.counter = 20
self.counter += 1
self.counter -= 1
self.counter *= 2
self.counter /= 2
self.counter %= 10
Unterstützt werden:
+=-=*=/=%=
Berechnungen¶
Unterstützte Operatoren:
+-*///%
Mit + können außerdem Listen und Zeichenketten verbunden werden:
Vergleiche¶
Unterstützt werden:
==!=<<=>>=
Beispiel:
Logische Operationen¶
Unterstützt werden:
andornot
Bedingungen müssen ein echtes logisches Ergebnis liefern. Zahlen werden nicht automatisch als Wahrheitswerte interpretiert.
Literale¶
Erlaubt sind:
NoneTrueFalse- Integer
- Float
- Zeichenketten
- Listen
- Tupel
- Dictionaries
Listen, Dictionaries und Zeichenketten¶
Listen¶
Unterstützte lesende Methoden:
copy()count()index()
Unterstützte verändernde Methoden:
append()clear()extend()insert()remove()reverse()sort()
Beispiel:
self.values.append(input)
if len(self.values) > 10:
self.values.remove(self.values[0])
return self.values
Auch die Zuweisung über einen vorhandenen Index ist möglich:
Der verwendete Listenindex muss bereits vorhanden sein.
Dictionaries¶
Unterstützte lesende Methoden:
copy()get()items()keys()values()
Unterstützte verändernde Methoden:
clear()update()
Direkte Zuweisungen sind ebenfalls möglich:
Dictionary-Schlüssel dürfen Zeichenketten oder Integer sein.
Zeichenketten¶
Unterstützte Methoden:
count()endswith()find()isalnum()isalpha()isdigit()join()lower()lstrip()replace()rsplit()rstrip()split()startswith()strip()upper()
Beispiel:
Direkte Eingangsdaten und Literale dürfen nicht verändert werden. Für Änderungen sollte zuerst eine eigene Liste oder ein eigenes Dictionary erzeugt werden.
Verfügbare Hilfsfunktionen¶
Folgende allgemeine Funktionen stehen zur Verfügung:
abs()all()any()bool()clamp()float()int()len()max()min()round()str()sum()
Beispiel:
Für clamp() muss die untere Grenze kleiner oder gleich der oberen Grenze sein.
Bei round(value, digits) muss digits zwischen -6 und 6 liegen.
Zeitfunktionen¶
Für Zeitfunktionen darf das Modul time verwendet werden:
Verfügbar sind:
time.time()time.ticks_ms()time.ticks_diff()time.localtime()time.mktime()time.sleep()
Beispiel:
Begrenzung von time.sleep()¶
Für time.sleep() gelten folgende Grenzen:
- maximal 5 Sekunden pro Aufruf
- maximal 10 Sekunden insgesamt pro Funktionsbaustein und Programmzyklus
Beispiel:
ist noch zulässig.
Ein weiterer Sleep-Aufruf im selben Programmzyklus würde das Gesamtlimit überschreiten.
Mehrere Handler-Aufrufe innerhalb desselben Zyklus teilen sich dieses Limit.
Lange Wartezeiten blockieren die Programmausführung. Auch wenn bis zu 10 Sekunden pro Zyklus technisch möglich sind, sollten normalerweise deutlich kürzere Wartezeiten verwendet werden.
JSON verarbeiten¶
Für JSON kann json verwendet werden:
Unterstützt werden:
json.loads()json.dumps()
Beispiel:
Alternativ kann auf Systemen mit MicroPython auch folgende Schreibweise verwendet werden:
Danach werden ebenfalls json.loads() und json.dumps() verwendet.
HTTP-Anfragen¶
Der Custom Code kann HTTP- und HTTPS-Anfragen ausführen.
Dazu wird requests importiert:
Auf MicroPython-Systemen ist außerdem folgende Schreibweise möglich:
Unterstützte Methoden:
requests.request()requests.head()requests.get()requests.post()requests.put()requests.patch()requests.delete()
Einfaches GET-Beispiel¶
import requests
response = requests.get(
"https://api.example.com/temperature",
timeout=5
)
response.raise_for_status()
data = response.json()
return data["temperature"]
POST mit JSON¶
import requests
body = {
"relay": True,
"source": "program"
}
response = requests.post(
"https://api.example.com/relay",
json=body,
timeout=5
)
response.raise_for_status()
return response.status_code
POST mit Benutzername und Passwort¶
import requests
response = requests.post(
"https://api.example.com/value",
json={"value": input},
auth=("username", "password"),
timeout=5
)
response.raise_for_status()
return response.status_code
Verfügbare Eigenschaften einer Antwort¶
response.status_coderesponse.okresponse.headersresponse.text
Verfügbare Methoden:
response.json()response.raise_for_status()response.close()
Die eigentliche Netzwerkverbindung wird intern kontrolliert. Der Custom Code erhält nur Zugriff auf die für ihn freigegebenen Informationen der Antwort.
Erlaubte HTTP-Ziele¶
Erlaubt sind:
http://https://- öffentliche Server
- private IPv4-Adressen im lokalen Netzwerk
Damit können beispielsweise Geräte im eigenen Netzwerk über ihre konkrete IPv4-Adresse angesprochen werden.
Nicht erlaubt sind unter anderem:
localhost- Loopback-Adressen wie
127.0.0.1 - Link-Local-Adressen
- Multicast-Adressen
- reservierte und Dokumentationsnetze
- Zugangsdaten direkt in der URL
- URL-Fragmente
- IPv6-Literale
- lokale Hostnamen wie
.local,.lan,.internaloder.home.arpa
Für Geräte im lokalen Netzwerk sollte deshalb die konkrete IPv4-Adresse verwendet werden.
Weiterleitungen sollten nach Möglichkeit vermieden werden. Für sicherheitsrelevante Anwendungen sollte direkt die endgültige URL angesprochen werden.
Die Zertifikatsprüfung bei HTTPS hängt von der im Wetterrelais eingesetzten Firmware ab.
HTTP-Grenzen¶
| Ressource | Grenze |
|---|---|
| HTTP-Anfragen pro Funktionsbaustein und Programmzyklus | 8 |
| Standard-Timeout | 5 Sekunden |
| Maximaler Timeout | 10 Sekunden |
| Maximale URL-Länge | 512 Zeichen |
| Request-Body | 16.384 Byte |
| Response-Body | 16.384 Byte |
| Eigene Request-Header | 16 |
| Response-Header | 64 |
| Länge eines Header-Namens | 64 Zeichen |
| Länge eines Header-Werts | 512 Zeichen |
| JSON-Verschachtelung | 8 Ebenen |
| JSON-Elemente | 256 |
Unterstützte Request-Argumente:
urltimeoutheadersdatajsonauth
data und json dürfen nicht gleichzeitig verwendet werden.
Nicht erlaubte Funktionen und Zugriffe¶
Der Custom Code wird absichtlich in einer eingeschränkten Umgebung ausgeführt.
Nicht erlaubt sind unter anderem:
- beliebige Imports wie
os,sys,machine,networkodersocket from ... import ...- Datei- und Flashzugriffe
- direkter Zugriff auf GPIOs
- direkter Zugriff auf Relais
- direkter Zugriff auf Busse oder andere Hardware
- Zugriff auf den übrigen Programmcode
exec()eval()__import__()getattr()globals()- private Attribute oder Namen mit führendem
_ - Klassen
lambdafor-Schleifenwhile-Schleifen- List-, Dict- und Set-Comprehensions
try,exceptundraisewithassertasync,awaitundyieldglobalundnonlocaldel- Rekursion
- direkte Socket-Zugriffe
- direkter Aufruf von
handler()
Schleifen sind bewusst nicht verfügbar. Wiederholte Abläufe können stattdessen über mehrere Programmzyklen, Listenmethoden oder geeignete Hilfsfunktionen umgesetzt werden.
Allgemeine Grenzen¶
Für jeden der drei Codebereiche gelten feste Ressourcenlimits.
| Ressource | Grenze |
|---|---|
| Zeichen pro Codebereich | 2.048 |
| Zeilen pro Codebereich | 64 |
| Tokens pro Ausdruck | 128 |
| Einrückung | maximal 16 Leerzeichen |
| Einrückungsstufe | 4 Leerzeichen |
| Ausgeführte Anweisungen pro Bereichsausführung | 128 |
| Eigene Funktionen pro Codebereich | 8 |
| Parameter pro Funktion | 8 |
| Verschachtelte Funktionsaufruftiefe | 4 |
| Elemente pro Liste, Tupel oder Dictionary | 128 |
| Verschachtelung eigener Werte | maximal 6 Ebenen |
| Länge einer Zeichenkette | 16.384 Zeichen |
| Größter zulässiger Zahlenbetrag | 9.007.199.254.740.991 |
| HTTP-Anfragen pro Zyklus | 8 |
time.sleep() pro Aufruf |
5 Sekunden |
time.sleep() insgesamt pro Zyklus |
10 Sekunden |
Leerzeilen und Kommentare zählen bei der Zeichen- und Zeilengrenze mit.
NaN ist als Zahlenwert nicht erlaubt.
Tabs sind im ausgeführten Code nicht zulässig. Einrückungen werden mit jeweils vier Leerzeichen dargestellt. Der Codeeditor unterstützt dabei die Tab-Taste und setzt die passende Einrückung automatisch als Leerzeichen um.
Code bearbeiten¶
Für jeden Bereich besitzt der Code-Baustein eine eigene Schaltfläche:
- Init-Code bearbeiten
- Update-Code bearbeiten
- Handler-Code bearbeiten
Die Schaltfläche zeigt zusätzlich an, ob der Bereich leer ist oder wie viele Zeilen Code enthalten sind.
Beim Anklicken öffnet sich ein größeres Codefenster. In dessen Kopfbereich wird angezeigt, wann der jeweilige Code ausgeführt wird.
Änderungen werden unmittelbar in den Code-Baustein übernommen. Es gibt keine zusätzliche Schaltfläche zum Übernehmen oder Abbrechen.
Das Fenster kann geschlossen werden über:
- das Schließen-Symbol oben rechts
- einen Klick außerhalb des Fensters
- die Escape-Taste
Das Schließen des Fensters verwirft keine Änderungen.
Die Änderungen befinden sich zunächst nur im aktuell bearbeiteten Programm. Damit der neue Code auf dem Wetterrelais ausgeführt wird, muss das Programm anschließend wie gewohnt mit Übertragen an das Gerät gesendet werden.
Einrückung im Codeeditor¶
Python verwendet Einrückungen zur Kennzeichnung zusammengehöriger Codebereiche.
Im Codeeditor gilt:
- Tab rückt um vier Leerzeichen ein.
- Umschalt + Tab entfernt eine Einrückungsstufe.
- Bei mehreren markierten Zeilen werden alle markierten Zeilen gemeinsam eingerückt oder ausgerückt.
Beispiele¶
Beispiel 1: Eingangswert begrenzen¶
Eingangstyp: Wert
Ausgangstyp: Wert
Init-Code¶
Update-Code¶
Handler-Code¶
Der Funktionsbaustein wartet auf einen Eingangswert und begrenzt ihn anschließend auf den Bereich von 0 bis 100.
Beispiel 2: Prozentwert auf 16 Bit skalieren¶
Eingangstyp: Wert
Ausgangstyp: Wert
Init-Code¶
Update-Code¶
Handler-Code¶
def scale_percent(value):
value = clamp(value, 0, 100)
return int(value * 65535 / 100)
if input == None:
return None
else:
return scale_percent(input)
Ein Eingangswert von 0 bis 100 wird auf einen Zahlenbereich von 0 bis 65535 skaliert.
Beispiel 3: Zähler über mehrere Programmzyklen¶
Eingangstyp: Kein Eingang
Ausgangstyp: Wert
Init-Code¶
Update-Code¶
Handler-Code¶
Der Zähler wird bei jedem neuen Programmzyklus einmal erhöht.
Beispiel 4: Wert über HTTP abrufen¶
Eingangstyp: Kein Eingang
Ausgangstyp: Wert
Init-Code¶
Update-Code¶
Handler-Code¶
import requests
response = requests.get(
self.url,
timeout=5
)
response.raise_for_status()
data = response.json()
return data["temperature"]
Der Funktionsbaustein ruft in jedem Programmzyklus einen Wert über HTTP ab und gibt ihn als Zahlenwert aus.
Fehlerverhalten¶
Der eingegebene Code wird geprüft, bevor er ausgeführt wird.
Fehler können beispielsweise entstehen durch:
- nicht erlaubte Imports
- falsche Einrückung
- einen fehlenden Rückgabewert im Handler
- Zugriff auf nicht angelegte
self-Variablen - Überschreiten der Code- oder Ressourcenlimits
- nicht erlaubte Funktionen oder Methoden
- einen Rückgabewert, der nicht zum eingestellten Ausgangstyp passt
Laufzeitfehler werden dem jeweiligen Code-Baustein zugeordnet, damit sich erkennen lässt, welcher Operator den Fehler verursacht hat.
Netzwerkfehler können dazu führen, dass eine Anfrage später erneut versucht wird. Programmier-, Typ- oder Validierungsfehler werden dagegen als Programmfehler behandelt.
Empfehlungen¶
Für die meisten Anwendungen hat sich folgende Aufteilung bewährt:
Init-Code¶
Dauerhafte Einstellungen und Zustände anlegen:
Update-Code¶
Arbeiten ausführen, die genau einmal pro Programmzyklus stattfinden sollen:
Handler-Code¶
Eingang prüfen, Ergebnis berechnen und zurückgeben:
Als Grundregel gilt:
- Init-Code: dauerhafte Variablen und Einstellungen anlegen.
- Update-Code: einmalige Arbeiten des aktuellen Programmzyklus durchführen.
- Handler-Code: den eigentlichen Ausgang berechnen.
return None: Der Ausgang kann momentan noch nicht bestimmt werden.- Jeder andere zum Ausgangstyp passende Rückgabewert bestimmt den Ausgang des Bausteins für den aktuellen Programmzyklus.
- Zustände, die nur einmal pro Zyklus verändert werden sollen, gehören in den Update-Code und nicht in den Handler.
- HTTP-Anfragen und
time.sleep()sollten möglichst kurz gehalten werden, damit der Programmablauf nicht unnötig blockiert wird.
Zusammenfassung¶
Mit dem Funktionsbaustein Benutzerdefinierter Code kann die Programmlogik des Wetterrelais gezielt erweitert werden. Er eignet sich insbesondere für:
- individuelle Berechnungen
- Wertebegrenzung und Skalierung
- Filter
- Zähler und Zustände über mehrere Programmzyklen
- Verarbeitung von Listen, Dictionaries und Zeichenketten
- JSON-Auswertung
- Zeitfunktionen
- HTTP- und HTTPS-Anfragen
- Anbindung lokaler Geräte über IPv4
- eigene Hilfsfunktionen
Der Funktionsbaustein arbeitet dabei in einer kontrollierten Umgebung mit festen Grenzen. Direkte Zugriffe auf Hardware, Dateien, Betriebssystemfunktionen oder interne Bestandteile des Wetterrelais sind nicht möglich.