Scripting mit p44Script

Diese Seite gibt eine Übersicht über die Programmiersprache p44script, die in den P44-Produkten zur Konfiguration und Erweiterung der Funktionalität zum Einsatz kommt. Es geht dabei vor allem die Konzepte in und um p44script herum.

Für eine detaillierte Beschreibung der Syntax und der Funktionen, die in p44script zur Verfügung stehen, dient gibt es die p44script-Kurzreferenz, welche übrigens auch offline in jedem P44-Gerät verfügbar ist (s. Link rechts unten bei Script-Eingabefeldern).

Wo können p44script-Skripte eingesetzt werden?


Die Programmiersprache p44script ist eine sogenannt "embedded" (eingebettete) Scriptsprache, die an verschiedensten Orten der Umgebung, in der sie eingebettet ist, über Scripts Funktionalität hinzufügen kann. Grundsätzlich ist p44script in beliebige C++-Projekte einbaubar, wenn die p44utils-Bibliothek verwendet wird.

In diesem Abschnitt sollen aber die verschiedenen Orte für die Anwendung von p44script ** innerhalb eines P44-DSB oder P44-LC-Geräts aufgezeigt werden.

Scriptkontexte

Weil die Scripte an verschiedenen Orten im System laufen können, gibt es auch verschiedene sogenannte Scriptkontexte. Ein Scriptkontext umfasst:

  • gemeinsame Variablen (Kontext-Variablen), die mit var erzeugt werden und aus allen Scripts, die in diesem Scriptcontext laufen, sichtbar sind, sowie lokale Funktionen (mit local function definiert). Aus anderen Scriptkontexten sind diese Variablen und Funktionen nicht sichtbar. Nur globale Variablen, die mit glob erzeugt werden, sind aus allen Kontexten sichtbar und auch veränderbar.
  • ein oder mehrere Scripts, die in diesem Kontext laufen können, u.U. sogar zur selben Zeit. Ein in einem Scriptkontext laufendes Script erzeugt mindestens einen sogenannten Thread (etwa: "Ausführungsstrang"), und kann mit dem concurrent-Konstrukt auch weitere Threads starten.
  • die Möglichkeit, alle in diesem Kontext laufenden Threads zu beenden. Zum Beispiel werden beim Aufruf einer Szene alle laufenden Scripte/Threads im Scriptkontext des betroffenen Ausgangs (devices) beendet, z.B. Szenenscripte (s. unten). Auch die abort()-Funktion erlaubt das Beenden aller Skripte im gleichen Scriptkontext.
  • möglicherweise kontext-spezifische Funktionen, um direkt mit dem Kontext (z.B. eines Geräts/devices) zu interagieren. Im Devicekontext zum Beispiel gibt es output, sensor(), input(), button() (und view bei LEDchain-Geräten), um auf Ein- und Ausgänge des jeweiligen Geräts zuzugreifen.

Neben diesen verschiedenen Kontexten gibt es auch noch den globalen Kontext. Dieser beinhaltet alle mit glob definierten globalen Variablen aus allen anderen Kontexten, ebenso alle mit function oder global function definierten Funktionen.

Der Maincontext - das "Hauptprogramm"

Es nur einen einzigen Maincontext pro Anwendung (P44-DSB- oder P44-LC-Gerät).

Im Maincontext laufen die folgenden Scripte:

Das mainscript
Das mainscript wird beim Aufstarten/Neustarten des P44-xx-Geräts (oder nach restartapp()) gestartet, und läuft ab dann parallel mit der sonstigen Funktion des Geräts. Es kann deshalb sowohl dazu verwendet werden, nur kurz beim Start einige Aktionen auszuführen, kann aber auch ein dauernd laufendes "Hauptprogramm" beinhalten.
Auf P44-Geräten ist er in der Weboberfläche unter p44script.html zu finden - d.h. wenn die normale Weboberfläche beispielsweise http://192.168.42.73 lautet, lässt sich das Mainscript unter http://192.168.42.73/p44script.html aufrufen.

Ab Firmware-Version 2.7.0/2.7.0.27 IDE benutzen!

Ab 2.7.0/2.7.0.27 ist der einfache Mainscript-Editor durch die viel komfortablere p44script-IDE ersetzt. Diese findet sich auf der Seite "ide.html" bzw. kann durch den entsprechenden Knopf "Edit Mainscript..." auf dem "System"-Tab geöffnet werden.

Der REPL
der REPL (Read-Execute-Print-Loop) dient zum zeilenweisen Eingeben und Ausprobieren von p44script-Befehlen.
Auf P44-Geräten ist er in der Weboberfläche unter repl.html zu finden - Mehr Informationen dazu siehe hier.

Ab Firmware-Version 2.7.0/2.7.0.27 IDE benutzen

Ab 2.7.0/2.7.0.27 kann anstatt des einfachen REPL alternativ auch die viel komfortablere p44script-IDE verwendet werden. Diese findet sich auf der Seite "ide.html" bzw. kann durch den entsprechenden Knopf "Show p44script IDE..." auf dem "System"-Tab geöffnet werden. Anders als der alte REPL können in der IDE-Konsole Befehle nicht nur im Maincontext ausgeführt werden, sondern auch in anderen Kontexten.

Der Evaluatorcontext - Evaluatoren

Evaluatoren sind Benutzerdefinierte Geräte, die einen oder mehrere Sensor- oder Digitaleingänge überwachen und auswerten ("evaluieren"), und daraus ein Resultat berechnen, welches im Fall von P44-DSB an den Digital Strom-Server (dSS) weitergeleitet wird. Damit sind Sensor-Auswertungen möglich, welche mit der App "Benutzerdefinierte Zustände" im dSS u.U. nicht oder nur schwierig umzusetzen sind. Ebenso können abgeleitete Sensorwerte mit einem Evaluator gebildet werden - z.B. die Gesamtleistung einer 3-Phasen Strommessung oder der Durchschnitt mehrerer Temperatursensoren.

Im Evaluatorcontext laufen die folgenden Scripte/Auswertungen:

Die Conditions
Das sind die Ausdrücke, die einen Evaluator auslösen (triggern).
Bei Evaluatoren mit Ja/Nein-Ausgangssignal oder bei Action-Evaluatoren gibt es je eine Bedingung fürs Einschalten und fürs Ausschalten. Beide werden im Evaluatorcontext ausgewertet. Es sind aber keine vollständigen Scripte, sondern nur Ausdrücke deren Resultat als true (!=0) oder false (==0) ausgewertet werden. Sie können keine Funktionen enthalten, deren Ausführung u.U. längere Zeit dauert wie delay() oder httprequest().
Bei Sensor-Evaluatoren, deren Ausgang ein Sensorwert ist, gibt es nur einen Ausdruck, dessen Resultat als Ausgangswerts des Sensors verwendet wird.
Die Action
Bei Action-Evaluatoren wird nicht ein Signal- oder Sensorwert beeinflusst, sondern das Actionscript ausgeführt. Dieses läuft auch im Evaluatorkontext, wie die Auslösebedigungen. Es ist deshalb möglich, in einer Auslösebedingung auf eine Variable Bezug zu nehmen, die im Actionscript verändert wird (damit das funktioniert, werden die Auslösebedingungen immer nach dem Ausführen des Actionscript nochmals ausgewertet, damit so eine "Rückkopplung" auch tatsächlich erkannt wird).

Rückkopplungen sind heikel

Obwohl es bei manchen Aufgabenstellungen nützlich sein kann, sind Rückkoppelungen (Actionscript verändert Werte, die in der Auslösebedingung vorkommen) heikel - bei (Denk-)fehlern kann es schnell dazu kommen, dass ein Evaluator sich quasi dauernd selber auslöst und so die Performance des Geräts beeinträchtigt.

Der Devicecontext - Scripting in einzelnen Devices

Jedes in einer P44-DSB oder P44-LC in der Geräteliste sichtbare Gerät (=Device) hat einen eigenen Devicecontext. Hier laufen Scripte, die im Wesentlichen dieses eine Gerät und seine Ein- und Ausgänge betreffen, und deshalb auch direkten Zugriff auf diese haben (s. output, sensor(), input() Scriptfunktionen).

Im Devicecontext laufen die folgenden Scripte:

Die Szenenscripte
Szenenscripte sind einer bestimmten Szene in einem bestimmten Device mit Ausgang zugeordnet, und werden immer dann ausgeführt, wenn die entsprechende Szene aufgerufen wird. Szenenskripte ermöglichen Übergangs- und auch dauerhafte Effekte (z.B. ein langsamer fortlaufender Farbwechsel).
Ein Szenenscript läuft im Devicecontext, aber immer nur eines. Wenn ein Szenenscript noch läuft, während schon wieder eine andere Szene aufgerufen wird, wird es abgebrochen - und, wenn vorhanden, das Szenenskript der neu aufgerufenen Szene gestartet.
Szenenscripte können in den Speziellen Szeneneinstellungen via P44-DSB oder P44-LC Webinterface erstellt werden.

Der Implementationskontext eines Scripted Device

Separat vom Devicecontext

Der Implementationskontext eines scripted device ist komplett getrennt vom normalen Devicecontext. Nur Scripted Devices, also kundenspezifische, in p44script programmierte Geräte, haben einen Implementationskontext, und stellt die Ebene dar, die bei anderen Geräten (DALI, EnOcean, hue etc.) bereits fest in der Firmware vorhanden ist. Auf der Ebene darüber, dem Devicecontext, ist es völlig unerheblich, ob das Gerät eine fest eingebaute Implementation oder eine in p44script hat, weshalb die zwei Kontexte auch getrennt bleiben müssen.

Im Implementationskontext laufen die folgenden Scripte:

Das Implementationsscript
Jedes scripted device hat sein eigenes Implementationsscript, das über den Bleistift-Button oder den "Edit Implementation script..."-Button im Info-Dialog des Geräts erreichbar ist.

Der Scriptcontext eines Triggers (nur bei P44-LC-xx)

Im Standalone-Controller P44-LC, also der Version des Produkts das ohne Digital Strom-Anbindung selbstständig funktioniert, gibt es zusätzlich zu den Devices die Triggers. Diese beinhalten eine Auslösebedingung und ein Aktionsscript, das beim Eintreffen der Bedingung ausgeführt (getriggert) wird. Die Auslösebedingung und das Aktionsscript laufen beide in einem eigenen, privaten Kontext des Triggers, dem Triggerkontext.

Scriptsprache

p44script orientiert sich in der Syntax stark an JavaScript (und dieses an C/C++) an. Hingegen was die verfügbaren Standard-Funktionen und Sprachkonstrukte betrifft, ist p44script absichtlich nicht dasselbe wie JavaScript. p44script ist konzipiert um Aufgaben zur Programmierung von Licht- und anderen Installationen möglichst einfach umsetzen zu können, und hat dafür spezifische Eigenschaften die es in JavaScript nicht gibt:

  • eine einfache Möglichkeit, mit dem concurrent-Konstrukt Codestücke zeitlich parallel zu anderen Abläufen auszuführen
  • die Fähigkeit, auf Ereignisse wie Sensorwertänderungen, Tastendrücke, Eingangsänderungen, Zeitabläufen aber auch Eintreffen von Netzwerkpaketen, Web-Zugriffen etc. mit dem on (...) { ... }-Konstrukt zu reagieren.
  • Unter den Standard-Funktionen gibt es etliche wie z.B. maprange(), cyclic() oder random(), welche in Automationsaufgaben oft vorkommende Problemstellungen bequem, solide und mit allen erforderlichen Optionen erledigen können - was in Standardsprachen natürlich auch möglich ist, aber mit weit mehr Aufwand.
  • Standard-Funktionen zur Ansteuerung von HTTP-APIs (httprequest(), websocket(), geturl(), puturl()) , lokal im Netz oder in der Cloud, und zum Auffinden von Geräten im lokalen Netz via DNS-SD (dnssdbrowse()).
  • Es gibt auch absichtlich Weggelassenes, z.B. bitwise And/Or/Xor. Diese sind zwar wichtig für Bitmanipulationen, aber nicht-Informatiker:innen schwer verständlich - in p44script gibt es dafür deshalb bequemere Funktionen bit(), setbit() und flipbit().
  • Zum einfachen Umgang mit Uhrzeiten, wie sie für Schaltaufgaben oft vorkommen, können Zeitwerte direkt als solche geschrieben werden, wie z.B. 12:30 (halb eins) oder 25.May odder 25.5. für Kalenderdaten.
  • Für Lichtsteuerungen ist oft der Sonnenstand wichtig; p44script kann mit sunrise(), sunset(), dawn() und dusk() die enstprechenden Zeiten für jeden Tag im Jahr berechnen (abhängig von den Geokoordinaten die für das Gerät eingestellt sind).
  • "Annotierte" Null-Werte helfen zu verstehen, weshalb eine Operation oder Funktion nicht das zurückgibt, was man vielleicht erwartet, indem der Nullwert nicht einfach "null" ist, sondern einen Erklärtext (die Annotation) mitführt, welche beim debuggen in der IDE oder im Log angezeigt wird.
  • Einfachen Zugriff auf die Komponenten des Systems:
    • Geräte: vom System gemanagte Leuchten, Sensoren, Tasten etc. via device()
    • Szenen: vom User eingestellte Kombinationen von Ausgangswerten auf einem oder mehreren Geräten, via scene()
    • Trigger: (nur P44-LC) vom User konfigurierte Bedingungen mit Aktionen, z.B. Schaltuhren, Reaktion auf Sensoren etc., mit trigger()
    • Views: (Setups mit LED-Ketten/Matritzen) visueller Aufbau von komplexen Lichtobjekten mit dem p44lrgraphics Subsystem, via view bzw. lgr (rootview).
    • I/O: Eingänge und Ausgänge der Hardware aller Art via digitalio(), analogio()
    • Subsysteme: Subsysteme wie SPI, I2C, modbus, Gleichstrom-Motoransteuerung, p44lrgraphics für LED-Graphik oder die features (s. unten)
    • Features: Subsysteme aus plan44-Projekten mit spezialisierter Funktionalität (etwa RFID-Leser für pseudonyme Besucheridentität in Ausstellungen, oder Ansteuerung von Splitflap-Displays), die aber u.U. dennoch nützlich sein kann. Details s. p44features auf Github.

Diese Liste soll einen Überblick geben, was es in p44script so gibt. Eine genaue Beschreibung aller Konstrukte, Operatoren, Funktionen und Systemobjekte findet sich in der Kurzreferenz), die auch in jedem P44-xx-Setup eingebaut verfügbar ist (Knopf Docs... im System-Tab und in der IDE, bzw. entsprechende Links unten an den Script-Textfeldern).