JavaScript
JavaScript ist die textbasierte Programmieransicht des IOZER basic. Sie eignet sich für kompakte Logik, komplexere Bedingungen, wiederverwendbare Abläufe und Integrationen, die mit Blockly unübersichtlich würden.
JavaScript-Code wird wie Blockly immer im Kontext eines Ereignisses ausgeführt. Das Programm läuft also nicht dauerhaft in einer Endlosschleife, sondern wird gestartet, wenn der konfigurierte Auslöser eintritt.
Ereigniskontext
Beim Start eines Ereignisses stellt die Firmware Kontextdaten bereit. In JavaScript stehen diese über ioz_event und ioz_event_context zur Verfügung. Beide Namen zeigen auf denselben Kontext des aktuell ausgeführten Ereignisses.
Der Kontext ist lesend zu verwenden. Welche Felder verfügbar sind, hängt vom Ereignistyp ab.
Allgemeine Felder:
| Feld | Bedeutung |
|---|---|
event_id |
ID des aktuell ausgeführten Ereignisses |
name |
Technischer Name des Ereignisses |
label |
Anzeigename des Ereignisses |
trigger_code |
Interner Ereignistyp |
source_no |
Nummer der Quelle |
timestamp |
Zeitstempel der Ausführung |
Zusätzliche Felder:
| Auslöser | Kontextfelder |
|---|---|
| Datenpunkt | datapoint_id, datapoint_name, value, last_value, valid, last_valid, state, last_state, unit, classification |
| Zeitplan | cron_expression |
| Manuell | param1 bis param4, abhängig von der Konfiguration des manuellen Ereignisses |
| Fehler | interface, error_code, error_message für 1-Wire-, Modbus- und MQTT-Fehler |
Beispiel für ein Datenpunkt-Ereignis:
if(ioz_event.datapoint_name = "taster_flur" && ioz_event.value = true) {
dp.set("licht_flur", true);
log.info("Flurlicht eingeschaltet");
}
Die Ereignisstruktur ist unter Ereignisse beschrieben.
Gerätefunktionen
JavaScript kann über IOZER-spezifische globale Objekte mit dem Gerät interagieren. Diese Objekte werden von der Firmware bereitgestellt und stehen in jedem Ereignis zur Verfügung.
Bei Datenpunkten kann ref entweder die numerische Datenpunkt-ID oder der technische Datenpunktname sein. Bei manuellen Ereignissen kann ref entsprechend die Event-ID oder der Event-Name sein.
| Objekt | Zweck |
|---|---|
system |
Systemfunktionen wie Warten oder Neustart auslösen |
mqtt |
MQTT-Nachrichten veröffentlichen |
dp |
Datenpunkte lesen, schreiben, schalten oder Status abfragen |
event |
Manuelle Ereignisse starten, stoppen oder abfragen |
log |
Meldungen in das Programm- oder Systemprotokoll schreiben |
Datenpunkte
Das Objekt dp ist die wichtigste Schnittstelle zwischen JavaScript, Hardware, Protokollen und Weboberfläche.
| Befehl | Beschreibung |
|---|---|
dp.get(ref, fallback?) |
Liest den aktuellen Wert eines Datenpunkts. Ist der Datenpunktzustand ungültig, wird fallback zurückgegeben, sofern angegeben, sonst null. |
dp.set(ref, value) |
Schreibt einen Wert in einen Datenpunkt. Der Wert muss zum Datentyp passen oder sinnvoll konvertierbar sein. Bei Erfolg wird true zurückgegeben. |
dp.toggle(ref) |
Schaltet einen booleschen Datenpunkt um und gibt den neuen Wert als true oder false zurück. |
dp.state(ref) |
Liefert ein Statusobjekt zum Datenpunkt, unter anderem mit id, name, label, valid, quality, updated, changed, datatype, unit und value. |
Beispiel:
const temperatur = dp.get("raumtemperatur", null);
if(temperatur !== null && temperatur > 28) {
dp.set("luefter", true);
}
const lichtAktiv = dp.toggle("licht_flur");
log.info("Flurlicht: " + String(lichtAktiv));
dp.state(ref) eignet sich, wenn nicht nur der Wert, sondern auch Qualität, Einheit oder Aktualisierungszeit relevant sind.
const zustand = dp.state("raumtemperatur");
if(!zustand.valid) {
log.warn("Raumtemperatur ist nicht gültig");
}
MQTT
| Befehl | Beschreibung |
|---|---|
mqtt.publish(topic, payload, qos?, retain?) |
Veröffentlicht eine MQTT-Nachricht. payload kann Text, Zahl oder Boolean sein. qos ist optional und standardmäßig 0, retain ist optional und standardmäßig false. Bei Erfolg wird true zurückgegeben. |
Beispiel:
mqtt.publish("iozer/status/luefter", "aktiv", 0, false);
Für normale Wertveröffentlichungen sollten bevorzugt Datenpunkt-MQTT-Funktionen genutzt werden. mqtt.publish ist sinnvoll für zusätzliche Meldungen, Integrationslogik oder projektspezifische Topics.
Manuelle Ereignisse
Das Objekt event arbeitet mit benutzerdefinierten manuellen Ereignissen. Hardware-, Schnittstellen- und Datenpunkt-Auslöser werden nicht direkt über event.trigger gestartet.
| Befehl | Beschreibung |
|---|---|
event.trigger(ref, delayMs?, repeat?, param1?, param2?, param3?, param4?) |
Startet ein manuelles Ereignis sofort oder verzögert. delayMs ist die Verzögerung in Millisekunden, repeat die Anzahl der Ausführungen. Bis zu vier Parameter werden im Zielereignis als ioz_event.param1 bis ioz_event.param4 bereitgestellt. |
event.stop(ref) |
Stoppt ein geplantes manuelles Ereignis. |
event.isRunning(ref) |
Gibt true zurück, wenn ein geplantes manuelles Ereignis noch aktiv ist. |
Beispiel:
if(dp.get("bewegung_flur", false)) {
event.trigger("licht_nachlauf", 30000, 1, "flur");
}
System
| Befehl | Beschreibung |
|---|---|
system.sleep(ms) |
Wartet innerhalb des aktuell ausgeführten Ereignisses für die angegebene Zeit in Millisekunden. Der Wert muss größer als 0 sein. |
system.reboot() |
Startet das Gerät neu. |
system.sleep blockiert die Ausführung des aktuellen Ereignisses. Lange Wartezeiten sollten daher vermieden und nach Möglichkeit über manuelle Ereignisse mit Verzögerung abgebildet werden.
Protokoll
| Befehl | Beschreibung |
|---|---|
log.debug(message) |
Schreibt eine Debug-Meldung. |
log.info(message) |
Schreibt eine Info-Meldung. |
log.warn(message) |
Schreibt eine Warnmeldung. |
log.error(message) |
Schreibt eine Fehlermeldung. |
Die Meldung sollte als Text übergeben werden. Wenn Zahlen oder boolesche Werte protokolliert werden, ist eine explizite Umwandlung sinnvoll.
log.info("Temperatur: " + String(dp.get("raumtemperatur", "unbekannt")));
Ungültige Referenzen, falsche Datentypen oder fehlgeschlagene Geräteaktionen lösen JavaScript-Fehler aus. Verwenden Sie daher eindeutige Datenpunkt- und Ereignisnamen und prüfen Sie externe Werte, bevor sie in Schaltlogik verwendet werden.
Typische Anwendungen
- mehrere Bedingungen kompakt kombinieren
- Werte berechnen, skalieren oder begrenzen
- Datenpunkte abhängig von Schnittstellenwerten setzen
- manuelle Ereignisse mit Parametern starten
- strukturierte Protokollmeldungen erzeugen
- komplexere MQTT- oder Modbus-Logik über Datenpunkte abbilden
Gute Praxis
- Halten Sie Ereignisse kurz und klar benannt.
- Verwenden Sie Datenpunkte statt direkter Hardwareabhängigkeiten, wenn die Logik schnittstellenübergreifend arbeitet.
- Prüfen Sie Werte auf Plausibilität, bevor Ausgänge geschaltet werden.
- Schreiben Sie gezielte Protokollmeldungen für Zustände, die bei Inbetriebnahme oder Service relevant sind.
- Vermeiden Sie dauerhafte Schleifen und lange blockierende Wartezeiten.
Für visuell nachvollziehbare Schaltlogik kann Blockly die bessere Wahl sein. Für fachliche Entkopplung und Schnittstellenlogik sollten zusätzlich Datenpunkte verwendet werden.