Grundlegende Ausdrücke

Literale

1234
ganzzahlige Zahl
1234.567
Fließkommazahl
true oder yes
boolesches true, Zahlenwert ist 1
false oder no
boolsch falsch, Zahlenwert ist 0
null oder undefined
kein Wert. Beachten Sie, dass p44script über annotierte Nullwerte verfügt, was bedeutet, dass in vielen Fällen null/undefined auch einen kurzen Text trägt, der seine Herkunft beschreibt. Dies ist bei der Fehlersuche nützlich, da es hilft zu verstehen, warum ein Wert null/undefiniert ist
12:30
Zeitangabe in Stunden und Minuten. Numerischer Wert ist die Anzahl der Sekunden seit Mitternacht
13:30:22
Zeitangabe in Stunden, Minuten und Sekunden. Numerischer Wert ist die Anzahl der Sekunden seit Mitternacht.
2.9.
Datumsangabe im Format Tag.Monat. (Punkt am Ende ist wichtig). Beispiel bedeutet 2. September. Der numerische Wert ist die Anzahl der Tage seit Beginn des aktuellen Jahres.
2.Sep
Datumsangabe im Format Tag.Monatsname (kein Punkt am Ende!). Monatsnamen sind jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec. Numerischer Wert ist die Anzahl der Tage ab Beginn des aktuellen Jahres.
wed
Wochentagsangabe. Wochentagsnamen sind sun, mon, tue, wed, thu, fri, sat. Numerischer Wert ist 0 für sonntags, 1..6 für montags..samstags.
'Text'
String-Literal, verwenden Sie zwei einfache Anführungszeichen hintereinander, um das einfache Anführungszeichen einzuschließen
"Text"
String-Literal mit C-ähnlichen Escapes (\n, \r, \t, \xHH und \\ können verwendet werden)
{ 'field1':42, 'field2':'hello' }
JSON-Objekt.
[ 42, 43, 'hallo' ]
JSON-Array.

Hinweis

JSON-Literale sind wirklich literal, Sie können keine Variablen anstelle von Feldnamen verwenden, wie es in JavaScript möglich ist.

Benannte Werte

In Ausdrücken können benannte Werte (z. B. Sensorwerte in Auswertebedingungen, oder Variablen in Skripten) verwendet werden. Einfache Werte bestehen nur aus einem Namen, aber es gibt auch strukturierte Werte, auf die mit der Punkt- und tiefgestellten Notation zugegriffen werden kann, zum Beispiel JSON-Objekte.

Sensor1
der Wert eines Sensors mit dem Namen sensor1.
sensor1.age
die Zeit in Sekunden, seit der Sensor namens sensor1 von der Hardware aktualisiert wurde.
sensor1.valid
true, wenn der Sensor mit dem Namen sensor1 einen aktuellen gültigen Wert hat (ein Sensor, der in Timeout gegangen ist oder seit dem letzten Neustart nie Daten von der Hardware erhalten hat, hat keinen Wert)
sensor1.oplevel
ein Wert zwischen 0 und 100, der den "Betriebszustand" des Sensors angibt. 0 bedeutet außer Betrieb, 100 bedeutet optimale Bedingungen, Werte dazwischen zeigen nicht-optimale Bedingungen an, wie z. B. schlechter Funkempfang oder niedriger Batteriestand. Wenn keine Informationen verfügbar sind, wird ein Nullwert zurückgegeben
jsonobj.fieldA
das Unterfeld namens fieldA in einem JSON-Objekt jsonobj. Mit jsonobj={ 'fieldA':42, 'fieldB':'hello' } wäre das Ergebnis also 42
jsonarr[1]
das Array-Element am numerischen Index 1 in einem JSON-Array jsonarr. Wenn also jsonvalue=[ 42, 'world' ], wäre das Ergebnis 'world'
jsonobj['fieldB']
das Teilfeld namens fieldA in einem JSON-Objekt jsonobj. Mit jsonobj={ 'fieldA':42, 'fieldB':'hello' } wäre das Ergebnis also 'hello'
jsonobj[0]
der Name des ersten (index==0) Teilfeldes in einem JSON-Objekt jsonobj. Mit jsonobj={ 'fieldA':42, 'fieldB':'hello' } wäre das Ergebnis also 'fieldA'. Auf diese Weise können json-Objekte untersucht werden, die Felder mit unbekannten Namen enthalten (z. B. von APIs zurückgegeben). Die Funktion elements() kann verwendet werden, um die Anzahl der Felder in einem Objekt zu ermitteln.

Operatoren

Operator Vorrang Beschreibung
! 6 (am höchsten) logisch NICHT
* 5 Multiplikation
/ 5 Division
% 5 modulo (Rest)
+ 4 numerische Addition, String-Verkettung, wenn der linke Ausdruck vom Typ String ist, JSON-Array-Verkettung, wenn beide Ausdrücke Arrays sind, JSON-Objekt-Merge, wenn beide Ausdrücke JSON-Objekte sind.
- 4 Subtraktion
== 3 Test auf Gleichheit
= 3 Test auf Gleichheit (je nach Kontext kann = auch eine Zuweisung sein, verwenden Sie ==, um Mehrdeutigkeit zu vermeiden)
!= oder <> 3 Test auf nicht gleich
< 3 Test auf kleiner als
> 3 Test auf größer als
<= 3 Test auf kleiner als oder gleich
>= 3 Test auf größer oder gleich
& oder && 2 logisches UND
| oder || 1 logisches ODER
:= 0 (niedrigste) Zuweisung
= 0 (niedrigste) Zuweisung (je nach Kontext kann = auch ein Test für gleich sein, verwenden Sie :=, um Mehrdeutigkeit zu vermeiden)

Allgemeine Funktionen

abs(a)
Absolutwert von a
chr(byte)
gibt einen String zurück, die aus einem einzelnen byte (Wert zwischen 0 und 255) besteht. Zu beachten ist, dass nicht alle Werte für byte einen gültigen (UTF8) String erzeugen. Diese Funktion ist jedoch in erster Linie dafür gedacht, binäre Byte-Strings zu erzeugen - p44script-Strings können 0 Bytes enthalten. Siehe auch ord().
cyclic(x, a, b)
gibt x mit Wrap-Around in den Bereich a..b zurück (ohne b, weil es gleichbedeutend mit a ist).
dawn()
gibt die ungefähre Zeit der Morgendämmerung am aktuellen Tag zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
day()
gibt den aktuellen Tag des Monats zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
dusk()
gibt die ungefähre Zeit der Abenddämmerung am aktuellen Tag zurück, aber kann keine zeitgesteuerten Aktionen auslösen.
elements(_array_or_object_)
Wenn array_or_object ein Array ist, gibt elements die Anzahl der Array-Elemente zurück. Wenn array_or_object ein JSON-Objekt ist, wird die Anzahl Felder zurückgegeben (deren Namen mit array_or_object[numeric_index] ermittelt werden können). Wenn array_or_object vom Typ her keine per Index zugreifbare Elemente haben kann, wird undefined zurückgegeben (aber die Zahl 0, wenn das Objekt oder der Array im Moment leer ist).
elements(object)
gibt die Anzahl der Elemente in object zurück, oder undefiniert, wenn array kein json-Wert ist
epochtime()
gibt die Unix-Epochenzeit zurück (Sekunden seit 1.1.1970 Mitternacht UTC), aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
epochdays()
gibt die Unix-Epochenzeit (Tage seit dem 1.1.1970) zurück, mit der Tageszeit als Bruchteil, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
error(irgendwas)
erzeugt einen Fehlerwert mit irgendwas als Fehlermeldung
errorcode(errvalue)
gibt den numerischen Fehlercode von errvalue zurück
errordomain(errvalue)
gibt den Fehlerdomänen-String von errvalue zurück
errormessage(errvalue)
liefert den String der Fehlermeldung von errvalue
eval(string)
wertet Zeichenkette als Ausdruck aus
find(haystack, needle [, from])
liefert die Position von needle in haystack wahlweise ab from, oder null, wenn nicht gefunden.
format(formatstring, value [, value...])
formatiert value_s als String gemäß printf-ähnlichem _formatstring (beachten Sie aber, dass formatstring nur eine Teilmenge von printf unterstützt. Insbesondere sind keine 'h', 'l' oder 'll' Längenangaben erlaubt (und auch nicht nötig). Erkannte Formatierungszeichen sind d,u,x,X für Ganzzahlformatierung, e,E,g,G,f für Fließkommazahlen und s für Zeichenketten.
formattime()
formattime(time)
formattime(formatstring)
formattime(time, formatstring)
Gibt die formatierte Zeit zurück. Ohne Argumente gibt formattime das aktuelle Datum und die Uhrzeit zurück, z. B. 2020-08-19 11:04:42. Mit nur einem numerischen Argument zeit wird die angegebene Zeit formatiert. Wenn time eine Tageszeit (zwischen 0 und 24*60*60 Sekunden) ist, wird nur die Zeit wie 11:04:42 angezeigt, andernfalls wird time als absoluter Unix-Epochen-Zeitstempel behandelt und standardmäßig als Datum+Zeit formatiert. Mit formatstring kann ein bestimmtes Datums- und Zeitformat eingestellt werden, wobei die Formatierungsmöglichkeiten der strftime() C-Standardfunktion genutzt werden.
frac(a)
gebrochener Wert von a (mit gleichem Vorzeichen wie a)
hour()
liefert die aktuelle Stunde, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
if(c, a, b)
gibt a zurück, wenn c als wahr ausgewertet wird, ansonsten b.
ifvalid(a, b)
gibt a zurück, wenn a ein gültiger Wert ist (nicht null oder Fehler), sonst b
int(a)
ganzzahliger Wert von a
isvalid(a)
liefert true, wenn a ein gültiger Wert ist (nicht null oder Fehler), sonst false
json(irgendetwas, [, kommentare_erlaubt])
versucht, irgendetwas als JSON zu interpretieren. Wenn irgendetwas ein String ist, wird der String als JSON-Text behandelt und geparsed (und nicht in einen einzelnen JSON-String umgewandelt). Wenn beim Parsen ein JSON-Syntaxfehler auftritt, gibt json einen entsprechenden Fehler zurück. Wenn kommentare_erlaubt auf true gesetzt ist, sind /* ... */-Kommentare im JSON-Text erlaubt (was nicht der JSON-Spezifikation entspricht, aber praktisch ist) Diese Funktion ist z.B. nützlich, um einen von einer API zurückgegebenen JSON-String als Struktur zugänglich zu machen.
jsonresource(path)
Lädt JSON aus path. Wenn path nicht absolut ist, wird er relativ zum Ressourcenpfad der Anwendung interpretiert (der normalerweise /usr/share/Anwendungsname ist). In JSON-Resourcefiles sind /* ... */-Kommentare erlaubt (obwohl das nicht der JSON-Spezifikation entspricht).
lastarg(a1, a2, ... , aN)
gibt aN zurück. Dies kann nützlich sein, um Seiteneffekte anderer Argumente zuerst auszuführen, bevor aN zurückgegeben wird
limited(x, a, b)
gibt min(max(x, a), b) zurück, d.h. x begrenzt auf Werte zwischen und einschließlich a und b
macaddress()
gibt die MAC-Adresse der drahtgebundenen Netzwerkschnittstelle als String mit 12 Hex-Ziffern zurück (keine Trennzeichen zwischen den Bytes)
maprange(x, a1, b1, a2, b2)
bildet x im Wertebereich a1..b1 linear auf den Wertebereich a2..b2 ab. Für alle Werte x vor a1 ist das Resulat a2, für alle Werte von x nach b1 ist das Resultat b2.
max(a, b)
gibt den größeren Wert von a und b zurück
min(a, b)
gibt den kleineren Wert von a und b zurück
minute()
gibt die aktuelle Minute zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
month()
liefert den aktuellen Monat (1..12), aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
nextversion()
gibt die nächste installierbare Firmware-Version zurück, wenn diese bekannt ist (von der automatischen Überprüfung oder einer kürzlich durchgeführten manuellen Überprüfung für ein Firmware-Upgrade). Ansonsten wird ein leerer String zurückgegeben.
number(irgendwas)
Versucht, irgendwas in eine Zahl zu konvertieren, gibt 0 zurück, wenn die Konvertierung fehlschlägt.
ord(string)
Gibt das Byte (Wert zwischen 0 und 255) zurück, das am Anfang von string gespeichert ist. Zu beachten ist, dass dieses erste Byte nicht unbedingt ein komplettes UTF8-Zeichen ist, sondern evtl. nur ein Teil davon. Diese Funktion ist jedoch in erster Linie für die Dekodierung binärer Byte-Strings gedacht - p44script-Strings können 0 Bytes enthalten. Siehe auch chr().
productversion()
gibt die Firmware-Version des Produkts zurück
random (a, b)
gibt einen (Fließkomma-)Pseudo-Zufallswert von a bis einschließlich b zurück
round(a [, p])
rundet a auf die optional angegebene Genauigkeit p (1=ganzzahlig=Standard, 0.5=Halbe, 100=Hunderter, etc...)
second()
gibt die aktuelle Sekunde zurück, kann aber nicht direkt zeitgesteuerte Aktionen auslösen.
string(irgendwas)
gibt eine String-Repräsentation von irgendetwas zurück. Gibt immer eine beschreibende Zeichenkette zurück, auch für null/undefinierte und Fehlerwerte.
strlen(string)
gibt die Länge von string zurück
substr(zeichenkette, von [, anzahl])
substr(string, from [, count])
gibt Zeichenkette ab from in string zurück, begrenzt auf count Zeichen, falls angegeben. Wenn von negativ ist, ist die Startposition relativ zum Ende von zeichenkette
sunrise()
Gibt die ungefähre Zeit des Sonnenaufgangs am aktuellen Tag zurück, kann aber nicht direkt zeitgesteuerte Aktionen auslösen (#timedtriggers).
sunset()
gibt die ungefähre Zeit des Sonnenuntergangs am aktuellen Tag zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
timeofday()
gibt die aktuelle Uhrzeit in Sekunden seit Mitternacht zurück, kann aber nicht direkt zeitgesteuerte Aktionen auslösen.
weekday()
liefert den aktuellen Wochentag (0..6), aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
year()
gibt das aktuelle Jahr zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.
yearday()
gibt das aktuelle Datum als Tageszahl im aktuellen Jahr zurück, aber kann nicht direkt zeitgesteuerte Aktionen auslösen.

Funktionen für zeitgesteuertes Triggern

Bitte beachten Sie, dass Sie die folgenden Funktionen verwenden müssen, um auf Zeit/Datum in Evaluator- oder Triggerbedingungen zu testen. Einfach etwas zu schreiben wie timeofday()==12:30 wird nicht funktionieren! Allgemeine Funktionen, die Zeitwerte wie sunrise oder dusk zurückgeben, sind dazu gedacht, als Argumente für is_time oder after_time verwendet zu werden, oder um zusätzliche Prüfungen zu dem Zeitpunkt zu implementieren, wenn der Ausdruck durch eine der folgenden Funktionen ausgelöst wird.

is_time(time)
gibt true zurück, wenn die Tageszeit time ist (mit 5 Sekunden Toleranz) und löst die Auswertung einmal pro Tag aus, wenn time erreicht wird.
is_weekday(weekday1 [, weekday2, ...])
gibt true zurück, wenn heute einer der angegebenen weekdayN-Argumente ist und löst die Auswertung zu Beginn der angegebenen Tage aus.
after_time(time)
gibt true zurück, wenn die Tageszeit time oder später ist und löst die Auswertung einmal pro Tag aus, wenn time erreicht ist.
between_dates(date1, date2)
gibt true zurück, wenn das aktuelle Datum zwischen date1 und date2 (einschließlich) liegt und löst die Auswertung am Anfang von date1 und am Ende von date2 aus
initial()
gibt true zurück, wenn dies ein initialer Lauf eines Trigger-Ausdrucks ist, d.h. nach dem Start oder nach Änderungen des Ausdrucks.
every(interval [, syncoffset])
gibt einmal alle interval (angegeben in Sekunden) true zurück und löst die Auswertung aus.
Hinweis: Bei der ersten Auswertung wird true zurückgegeben, oder, wenn syncoffset gesetzt ist, bei der nächsten ganzzahligen Anzahl von Intervallen, berechnet ab Tagesbeginn + syncoffset.
So wird every(0:30,0:22) einmal jede halbe Stunde ausgelöst, beginnend um 0:22, dann 0:52, 1:22, ...

Achtung - Vorsicht mit kurzen Intervallen

Seien Sie vorsichtig mit every() und kurzen Intervallen, da das sehr häufige Ausführen von Skripten die Leistung des Geräts beeinträchtigen kann!

testlater(Sekunden, timedtest [, retrigger])
gibt beim ersten Aufruf undefined/null zurück, plant aber eine erneute Auswertung nach gegebenen Sekunden und gibt dann den Wert von test zurück. Wenn retrigger true ist, dann wird die Neuauswertung im Intervall von Sekunden wiederholt (mit Vorsicht verwenden!)

Skripte

Vollständige p44Skripte (über einzelne Ausdrücke wie oben beschrieben hinaus) können verschiedene Dinge tun, indem sie die unten beschriebenen Funktionen verwenden. Die Skriptsprache hat eine Syntax, die ähnlich zu JavaScript oder C ist, aber bei weitem nicht identisch.

Kommentare

/* Kommentar */
Kommentar im C-Stil
// comment
Kommentar im C++-Stil wird bis zum Ende der Zeile fortgesetzt

Deklarationen

Der erste (optionale) Teil eines Skripts kann Deklarationen von globalen Variablen und Funktionen sein. (Handler können auch im Deklarationsteil stehen, wenn ihre Auslösebedingung keine erst zur Laufzeit des Skripts erzeugte Objekte referenziert) Die erste Nicht-Deklarationsanweisung in einem Skript beendet den Deklarationsteil. Deklarationen können also nicht mit eigentlichen Skriptanweisungen gemischt werden. Eine Ausnahme bilden Handler (s. oben) und globale Variablendeklarationen; diese können sowohl im Deklarationsteil als auch gemischt mit normalen Skriptanweisungen vorkommen.

Globale Variablen

glob g
global g
Deklaration der globalen Variable g.
Bitte beachten: eine Deklaration einer globalen Variablen ohne Initialisierung ist auch außerhalb des Deklarationsteils eines Skripts möglich (insbesondere in Skripten, die keine Deklarationen zulassen, wie z. B. P44-DSB-Auswerteraktionen oder Szenenskripte).
glob g = 78/9
Deklaration und Initialisierung der globalen Variable g.
Zu beachten ist, dass der Initialisierungsausdruck nur aus Konstanten oder anderen globalen Variablen bestehen kann, die bereits definiert sind.
Lokale Variablen und kontextabhängige Funktionen und Objekte sind zur Deklarationszeit nicht verfügbar.
Die Initialisierung von globalen Variablen sind nur im Deklarationsteil eines Skripts möglich (und nicht alle Skripte erlauben überhaupt Deklarationen, z. B. können P44-DSB-Evaluator-Aktionen oder Szenenskripte keine Deklarationen enthalten).

Sichtbarkeit globaler Variablen

Globale Variablen sind wirklich global, d.h. sie sind aus allen Scripten und Script-Teilen (etwa Auslösebedigungen, Szenenscripte, Trigger etc.) im ganzen System sichtbar. Es ist daher zu empfehlen, eindeutige Namen zu verwenden, die nicht zufällig anderswo auch vorkommen können. Generell sollten auch keine globalen Variablen verwendet werden, wenn Kontext-Variablen auch ausreichen.

Funktionen

function hallo()
{
  log('Hallo Welt');
}

Deklariert eine global verfügbare Funktion namens hello, die den Text 'Hallo Welt' protokolliert.

function sum(a,b)
{
  var c = a+b
  return c
}

Deklariert eine global verfügbare Funktion namens sum mit zwei Argumenten, die in einer lokalen Variable c (die nur während der Ausführung der Funktion für diese privat existiert) die Summe berechnet und zurückgibt.

Sichtbarkeit von Variablen in Funktionen

In Funktionen sind die mit var lokal definierten Variablen, die Variablen des Kontexts, aus dem die Funktion aufgerufen wird (s. Lokale Variablen) und schliesslich die globalen Variablen sichtbar. Wenn eine in der Funktion definierte Variable denselben Namen hat wie eine des aufrufenden Kontexts oder eine globale Variable, dann wird in Ausdrücken und Zuweisungen die lokale Variable verwendet.

(Event-)Handler

Ein handler ist ein spezielles Konstrukt, das p44Script bietet, um auf einfache Weise auf asynchrone Ereignisse aller Art, wie z.B. die Veränderung eines Sensorwertes, einen Tastendruck, ein Web-Zugriff, das Beenden eines threads, das Erreichen einer bestimmten Tageszeit oder Ablauf eines Intervals u.v.a.m zu reagieren.

Im Prinzip sind handler Deklarationen (ähnlich wie Funktionen werden sie nicht sofort ausgeführt, sondern nur für eine spätere Ausführung definiert). Deshalb werden sie in diesem Abschnitt beschrieben.

Allerdings gibt es Situationen, wo die Auslösebedingung eines handlers sich auf ein Objekt bezieht, das erst im Verlauf der Skriptausführung überhaupt erzeugt wird. In solchen Fällen kann der Handler erst danach angelegt werden, und kommt so in den Anweisungs-Teil zu stehen, wie in diesem Beispiel:

var s = udpsocket("127.0.0.1", 4242, true, true);
on (s.message()) as msg
{
  log('Nachricht auf UDP-Port 4242: '+string(msg))
}

Dies erstellt und öffnet zunächst einen Netzwerk-Socket, der auf UDP-Pakete an Port 4242 lauscht, und definiert dann einen Handler, der ausgelöst wird, sobald ein UDP-Paket ankommt. (Um ein UDP-Testpaket auf einer Unix-Befehlszeile zu senden, geben Sie zum Beispiel ein: echo -n "Test" | socat stdin "udp-sendto:127.0.0.1:4242")

Die folgenden Beispiele hingegen nehmen nur Bezug auf Objekte, die beim Start des Scripts schon existieren, und können deshalb im Deklarationsteil stehen:

on (after_time(12:00))
{
  log('Es war Mittag vor ' + string(timeofday()-12:00) + ' Sekunden')
}

Definiert einen Event-Handler (ein Stück Code, das ausgeführt wird, wenn eine bestimmte Bedingung erfüllt ist).

Dieser Handler wird ausgelöst, wenn die lokale Zeit die Mittagszeit (12:00) überschreitet und protokolliert die Anzahl der seit Mittag tatsächlich verstrichenen Sekunden - denn wenn dieser Handler zu einem beliebigen Zeitpunkt nach 12:00 installiert wird, wird er sofort einmal ausgeführt.

Standardmäßig werden Handler ausgeführt, wenn sich die Triggerbedingung von false zu true ändert (aber nicht, wenn sie sich von true zu false ändert).

on (every(0:15, 0))
{
  log('eine weitere Viertelstunde ist vergangen');
}

Definiert einen Eventhandler, der jede ganze Viertelstunde ausgeführt wird.

on (sensor1>20) toggling
{
  log('sensor1 ist ' + sensor1);
}

Definiert einen Event-Handler, der immer dann ausgelöst wird, wenn die Bedingung von false auf true oder umgekehrt umschaltet. Zu beachten ist, dass sensor1 eine Ereignisquelle sein muss, damit dies funktioniert. Kontexte, die Hardware-Eingänge wie z. B. Sensoren haben, stellen diese normalerweise als Ereignisquellen zur Verfügung (z.B. in P44-DSB Evaluatoren). Beispielsweise sind valuesource() oder device.sensor() Ereignisquellen.

on (sensor2) changing
{
  log('sensor2 ist ' + sensor2)
}

Definiert einen Event-Handler, der immer dann auslöst, wenn Bedingungsausdrücke neu ausgewertet werden und ein anderes Ergebnis als bei der letzten Auswertung erhalten.

on (sensor2) evaluating
{
  log('sensor2 ist ' + sensor2)
}

Definiert einen Event-Handler, der immer dann ausgelöst wird, wenn der Bedingungsausdruck ausgewertet wird, auch wenn sich das Ergebnis nicht ändert. Hinweis: Verwenden Sie dies mit Vorsicht, je nach den beteiligten Ereignisquellen kann dies dazu führen, dass der Handler sehr oft ausgeführt wird, was Performance-Probleme verursachen kann.

on (sensor1+sensor2) changing as sensorsum
{
  log('sensor1+sensor2 ist ' + sensorsum)
}

Definiert einen Event-Handler, der immer dann auslöst, wenn sich die Summe von sensor1+sensor2 ändert. Der Teil sensorsum speichert das Ergebnis des Trigger-Ausdrucks in der Variablen sensorsum.

on (sensor1>22) stable 0:05 as sens
{
  log('sensor1: stabil für 5 Minuten bei > 22, aktuell: ' + sens)
}

Definiert einen Event-Handler, der auslöst, wenn sensor1 für mindestens 5 Minuten über 22 bleibt.

on (featureevent()) as event
{
  log('Ereignis empfangen ' + Ereignis)
}

Definiert einen Event-Handler, der immer dann auslöst, wenn featureevent() ausgelöst wird und speichert das Ereignis in der Variablen event. Beachten Sie, dass bei Ereignisquellen, die eindeutige Ereignisse liefern, wie es featureevent() tut, das Speichern des tatsächlichen Auslösewerts in einer Variablen mit as wichtig ist.

Warnung

So mächtig die Handler auch sind, es ist auch möglich, Triggerbedingungen zu konstruieren, die zu einer sehr häufigen Ausführung des Handlers führen und damit potentiell den normalen Betrieb des Gerätes blockieren oder verschlechtern.

Lokale Variablen

var a
erzeugt eine skript-Kontext-lokale oder funktions-lokale (wenn in einer Funktion benutzt) Variable a (anfangs auf undefined gesetzt. Wenn a bereits existiert, passiert nichts.
var a = 7
Definition einer skript-Kontext-lokale oder funktions-lokale Variable a und Zuweisung eines Anfangswertes. Wenn die Variable bereits existiert, ist dies wie eine normale Zuweisung.

Variablenkontexte

Mit var erzeugte Variablen sind entweder komplett lokal (wenn sie innerhalb einer Funktion definiert werden) oder lokal zum jeweiligen Script-Kontext, und werden dann Kontextvariable genannt. Es gibt verschiedene Kontexte mit je eigenen Variablen. In einem P44-DSB- oder LC-Gerät z.B. laufen alle Szenenskripte einer Leuchte in einem Script-Kontext dieser Leuchte, d.h. die Szenenscripte untereinander sehen dieselben lokalen Variablen, aber andere Leuchten oder sonstige Geräte haben darauf keinen Zugriff (und können deshalb ohne Konflikte eigene Variablen mit gleichem Namen verwenden).

threadvar t
threadvar t = 7
Definition einer thread-lokalen Variable t (und ggf. Zuweisung eines Anfangswertes). Im Unterschied zu var hat diese Variable für jeden laufenden Ausführungsstrang (also z.B. Ausführung eines on(...) {...} oder catch {...}-Handlers) einen privaten Wert.

Automatisch erzeugte thread-Variablen

Thread-Variablen werden auch durch on(...) as variablenname {...} oder catch as variablenname {...} automatisch erzeugt, da der Wert bei jedem (u.U. parallel erfolgenden) Durchlauf des Codes u.U. ein anderer ist. (Hingegen erzeugt concurrent as variablenname keine Thread-Variable, sondern eine im Kontext des Scripts das concurrent ausführt.)

Anweisungen

glob b
Erzeugt eine globale Variable b (alle Skripte und Bedingungsausdrücke können auf sie zugreifen). Globale Variablen können (und sollten i.d.R.) auch vor dem Start des Scripts deklariert werden, siehe Deklarationen.
glob b = 42
Erzeugt eine globale Variable b und weist ihr einen Anfangswert zu. Siehe auch Deklarationen.
unset b
Entfernen einer (lokalen oder globalen) Variablen namens b.
unset a.b
unset a['b']
Entfernen des Feldes b aus der Objektvariablen namens a.
unset c[2]
Entfernen des Elements mit dem Index 2 (= drittes Element) aus einem Array namens c.
a := 3*4
Zuweisung des Ergebnisses eines Ausdrucks an a
a = 3*4
Einfaches Gleichheitszeichen wird ebenfalls als Zuweisung behandelt
let a = 3*4
let kann verwendet werden, um deutlicher zu zeigen, dass es sich um eine Zuweisung handelt (ist aber völlig optional)
a = 7; b = 3; c = a*b;
Mehrere Anweisungen können durch Semikolon getrennt in eine Zeile geschrieben werden
{ a = 42; b = 23; scene("bright"); }
Block aus mehreren Anweisungen

Kontrollfluss

if (a>0) b := 7

bedingte Ausführung der Zuweisung b:=7, wenn a größer als Null ist.

if (a>0) b := 7 else b := 19

Bedingte Ausführung der Zuweisung b:=7 mit else-Anweisung, die ausgeführt wird, wenn die Bedingung nicht wahr ist.

if (a>0) { b := 7; c := 44 } else { b := 0; c := "ein String" }

Bedingung mit Anweisungsblöcken.

while (i>0) { i := i-1; log(5, "i ist jetzt: " + i); }

Wiederholung (Schleife) des Anweisungsblocks, solange i größer als Null ist.

break

verlässt eine while Schleife.

continue

startet die nächste Iteration in einer while Schleife.

return

beendet das aktuelle Skript mit null/undefiniertem Rückgabewert.

return value

beendet das aktuelle Skript und gibt value zurück.

try { statements; } catch { handling_statements }

Wenn eine der statements einen Laufzeitfehler erzeugt, werden die handling_statements ausgeführt.

try { statements; } catch as error_var { handling_statements }

wenn eine der statements einen Laufzeitfehler erzeugt, werden die handling_statements ausgeführt und können error_var verwenden, um den Fehler zu untersuchen.

throw(anything)

erzeugt einen Laufzeitfehler mit anything als Fehlermeldung. Wenn anything bereits ein Fehlerwert ist, wird der Fehlerwert als solcher erneut ausgelöst.

Gleichzeitigkeit (Threads)

p44script verfügt über ein sehr komfortables Konstrukt, um gleichzeitig ablaufende Sequenzen von Operationen zu erzeugen, etwas, das in der Automatisierung oft benötigt wird. Eine gleichzeitig ablaufende Sequenz von Skriptanweisungen wird auch als Thread bezeichnet Beachten Sie, dass Ereignis-Handler, wie oben gezeigt, auch gleichzeitig mit anderen Skript-Aktivitäten ausgewertet und ausgeführt werden. Bei komplexeren Setups kann es notwendig sein, für gewisse Sequenzen sicherzustellen, dass sie sequentiell ablaufen. Dazu gibt es lock(), womit threads sich abstimmen können.

concurrent {
  while(true) { log('blink1'); delay(3) }
}
concurrent {
  while(true) { log('blink2'); delay(2.7) }
}
delay(0:02); abort();

lässt zwei asynchrone Blinksequenzen parallel laufen. Nach 2 Minuten werden beide gleichzeitigen Threads mit der Funktion abort() gestoppt.

concurrent as blinker {
  while(true) { log('blink'); delay(2) }
}
delay(0:02); abort(blinker)

Startet eine gleichzeitige Blinksequenz und speichert eine Referenz darauf als Variable namens blinker.

Nach zwei Minuten kann die Variable als Argument für abort() verwendet werden, um einen Thread gezielt zu stoppen.

concurrent as task1 { delay(random(2,5)); log('task1 done') };
concurrent as task2 { delay(random(2,5)); log('task2 done') };
await(task1,task2)
log('eine der beiden Tasks erledigt')
await(task1)
await(task2)
log('beide Tasks sind jetzt erledigt')

Startet zwei gleichzeitige Tasks mit einer zufälligen Dauer zwischen 2 und 5 Sekunden.

Die Funktion await() kann verwendet werden, um auf die Fertigstellung eines ihrer Argumente zu warten. Die Verwendung eines separaten await()-Aufrufs für jeden Thread führt zur Beendigung, wenn alle Aufgaben erledigt sind. Bei komplizierter Parallelität siehe auch lock() und signal() zur Synchronisierung von Threads.

Allgemeine Funktionen innerhalb von Skripten

abort()
bricht alle gleichzeitig laufenden Threads ab, außer dem Thread, von dem aus abort() aufgerufen wird.
abort(a [, abortresult, [ self]])
bricht den Thread namens a ab, d.h. den Thread, der mit concurrent as a {...} gestartet wurde. Wenn abortresult nicht null gesetzt ist, wird es als Endresultat des Threads verwendet (das z.B. von await() zurückgegeben wird). Wenn self nicht gesetzt ist, und a der eigene Thread ist (also der von dem aus abort() aufgerufen wurde), dann wird dieser nicht abgebrochen, weil das meistens nicht beabsichtigt ist und schwierig zu debuggen - falls doch, kann self gesetzt werden.
await(a [,b,...] [, timeout])
wartet auf ein oder mehrere Ereignisse, z. B. eintreffen eines Signals (s. signal()) oder die Beendigung von Threads, und gibt den Wert des Ereignisses zurück. Wenn timeout verwendet wird, beendet await das Warten nach der angegebenen Zeit und gibt undefined zurück.
delay(seconds)
verzögert die Skriptausführung um seconds (Fliesskommazahl, auch Sekundenbruchteile sind möglich)
httprequest(request [, data])

Dies ist eine verallgemeinerte Funktion, die anstelle von geturl(), puturl(), posturl() verwendet werden kann, wenn http-Requests mit speziellen Headern, Zertifikatprüfung, Client-Zertifikat etc. benötigt werden. Alle Parameter sind ein einem request JSON-Objekt zu übergeben:

  • url: Die komplette URL. Kann ein ! als erstes Zeichen enthalten, um Zertifikatsprüfung bei https-Verbindungen zu verhindern.
  • method : Optional, ohne Angabe wird GET verwendet.
  • data : Zu sendende Daten für PUT und POST, kann auch als zweiter Parameter der Funktion direkt übergeben werden (insbesondere notwendig wenn es sich um einen binärstring handelt).
  • timeout : optionaler timeout in Sekunden.
  • user : optionaler Username für http auth (kann auch als Teil der URL übergeben werden).
  • password : optionales Passwort für http auth (kann auch als Teil der URL übergeben werden).
  • headers : optionales JSON-Objekt, das zu sendende http-Header als Name/Wert-Paare enhält. Wenn kein Content-Type dabei ist, wird dieser Header automatisch aus den übergebenen Daten bestimmt (html oder json).
  • clientcert : optionaler Pfad zu einem zu verwendenden Client-Zertifikat.
  • servercert : optionaler Pfad zu einem zu verwendenden Root-Zertifikat oder Zertifikats-Directory für die Prüfung des Server-Zertifikats. Wird ein Leerstring angegeben, wird das Server-Zertifikat nicht geprüft (was auch mit einem ! vor der url erreicht werden kann, s. oben). Standardmässig wird das Serverzertifikat mit den Root-Zertifikaten des Systems geprüft.
geturl(url [,timeout])
Gibt die Antwort einer GET-Anfrage an (http oder https) url zurück, bricht nach timeout Sekunden ab, falls angegeben
lock([entered])
Erzeugt ein Lock-Objekt, welches mit seinen zwei Methoden .enter() und .leave() zur Synchronisation parallel laufender Threads verwendet werden kann. Wird entered==true angegeben, dann wird das Lock bei der Erzeugung schon für den aufrufenden Thread reserviert. Normalerweise weist man ein erzeugtes lock einer Variablen zu: var l = lock(). Der Wert des Locks ist 0 wenn es frei ist, andernfalls gibt es die Verschachtelungstiefe der enter()-Aufrufe des Threads an, der momentan das Lock reserviert hat.
Üblicherweise wird enter() in einer Bedingung verwendet:
var lk = lock()

// ...

if (lk.enter(0:03)) {
  // Sequentiell auszuführender Code
  // ...
  lk.leave()
}
else {
  log("3min timeout")
}
lk.enter([timeout])
Wartet, bis das Lock lk frei ist. Ohne Angabe von timeout wird unbestimmt lange gewartet. timeout kann 0 sein, um das Lock nur zu testen. Die Funktion gibt true zurück wenn das Lock für den aufrufenden Thread reserviert werden konnte. Sie gibt false zurück, wenn das Lock innerhalb des angegebenen timeout nicht reserviert werden konnte, oder wenn das Lock selber gelöscht wird (etwa mit unset).
lk.leave()
Gibt das Lock lk frei. Wenn andere Threads auf die Freigabe warten, erhält derjenige Thread Zugriff, der als erster lk.enter() aufgerufen hatte. leave() gibt true zurück, wenn damit tatsächlich eine Freigabe erfolgt ist. leave() von einem Thread aus, der nicht vorhher enter() aufgerufen hat, gibt false zurück und bewirkt nichts.

Warnung - Vorsicht vor deadlocks

Bei unsauberer Verwendung von Locks kann man leicht in die Situation geraten, dass zwei Threads je ein Lock reserviert haben, und gegenseitig auf die Freigabe des Locks des anderen Threads warten, was nie eintreffen kann. Das nennt sich deadlock und muss vermieden werden. Es empfiehlt sich deshalb, enter mit timeout zu verwenden, damit sich eine Script-Applikation nicht komplett blockieren kann.

log([loglevel, ] logmessage [, value...])
schreibt eine Meldung in die Logdatei der Anwendung. Wenn loglevel weggelassen wird, wird 5 (LOG_NOTICE) verwendet. Wenn nach logmessage weitere Argumente folgen, wird logmessage als Formatstring behandelt, so wie in der Funktion format() (s. dort).
loglevel()
gibt den aktuellen Log-Level zurück
loglevel(level [, deltatime])
ändert den Log-Level der Anwendung auf level. Wenn deltatime gesetzt ist, zeigen die Zeitstempel auch die Zeitdifferenz zum vorherigen Log-Eintrag in mS an.
logleveloffset(offset)
Ändert den Log-Level-Offset des Kontexts, in dem das Skript läuft, auf offset. Dies erlaubt es, einen Teil einer Anwendung selektiv mehr oder weniger ausführlich im Protokoll darzustellen.
posturl(url [,timeout][,data])
sendet data (muss ein String sein) mit POST an url, gibt Antwort zurück, bricht nach timeout Sekunden ab, wenn angegeben
puturl(url [,timeout][,data])
sendet data (muss String sein) mit PUT an url, gibt Antwort zurück, bricht nach timeout Sekunden ab, wenn angegeben
readfile(filename)
liest das File filename als String.

Hinweis

Um Pfade für filename zu verwenden, muss der Userlevel >=1 sein (Standard-Userlevel für Produktionsgeräte ist 0). Andernfalls können nur Files aus dem p44script Datenverzeichnis gelesen werden, oder wenn der Pfad mit "_/" beginnt, aus dem p44script-Temporärverzeichnis.

shellquote(argument)
gibt argument als String interpretiert und in einfache Anführungszeichen gesetzt zurück, so dass es sicher als einzelnes Shell-Argument funktioniert (auch wenn argument selber einfache Anführungszeichen enthält), und keine Shell-Variablen expandiert werden.
signal()
erzeugt ein "signal"-Objekt, das einer (evtl. globalen) Variablen zugewiesen werden kann. Threads können mit await() auf das Eintreffen des Signals warten, oder die Signal-Variable kann in on()-Handlern als Auslösebedingung verwendet werden. Das Signalobjekt hat eine Methode send(), mit der das Signal ausgelöst (versendet) werden kann.
system(commandline)
führt commandline über die Shell der Plattform aus und gibt die Ausgabe als String zurück.

Hinweis

Die Funktion system() ist nur verfügbar, wenn der Userlevel >=2 ist (Standard-Userlevel für Produktionsgeräte ist 0)

Warnung

Da die Funktion system() jeden Befehl auf OS-Level aufrufen kann, kann sie die Firmware ernsthaft beschädigen, bis hin zum Bricking des Gerätes. Deshalb ist sie standardmäßig nicht aktiviert. Wenn Sie einen DIY P44-DSB-X haben, können Sie den Userlevel auf >=2 setzen, um sie zu benutzen, aber seien Sie vorsichtig!

udpsocket(host, port, receive, nonlocal, broadcast)
gibt einen UDP-Socket zurück, der zum Senden von Paketen an host:port konfiguriert ist. Verwenden Sie die Methode .send(string), um Daten zu senden.
Wenn receive true ist, kann der Socket auch UDP-Pakete empfangen (über seine Methode .message(), die in on()-Anweisungen als Trigger verwendet werden kann.
Wenn nonlocal wahr ist, kann der Socket auch UDP-Pakete empfangen, die von anderen Hosts als nur localhost stammen (was der Standard ist)
Wenn broadcast wahr ist, kann der Socket Broadcast-Pakete senden und empfangen.
Üblicherweise weist man den Rückgabewert dieser Funktion einer Variablen zu: var udpsocket_var = udpsocket(...) um die weiter untenbeschriebenen Methoden aufrufen zu können.
udpsocket_var.message()
Gibt die letzte auf dem Socket empfangene UDP-Nachricht zurück. Das Ergebnis ist eine Ereignisquelle und kann in on()-Anweisungen als Trigger-Bedingung verwendet werden und kann auch await()-ed werden
udpsocket_var.send(string)
sendet string als UDP-Paket
undeclare()
Löscht alle Funktions- und Handler-Definitionen, die nicht Teil eines gespeicherten Skripts sind, sondern ad-hoc erstellt wurden, zum Beispiel aus einer interaktiven Skript-Befehlszeile (einer REPL = Read-Execute-Print-Loop).
Beachten Sie, dass Funktionen und Handler, die in einem in der Anwendung gespeicherten Skripttext definiert sind (z. B. Trigger-Aktionen, Szenenskripte usw.), an diese Skripttexte gebunden bleiben, d. h. sie werden entsprechend den Änderungen im Skripttext aktualisiert (oder entfernt) und werden nicht durch undeclare() entfernt.
urlencode(text [, x-www-form-urlencoded])
Encodiert den text für die Verwendung in einer URL oder, wenn x-www-form-urlencoded true ist, für das Senden von Formularfeldern in POST-Daten.
websocket(url [, protocol [,pinginterval]])
Erstellt eine Websocket-Verbindung zur angebenen url mit dem Protokoll ("Sec-WebSocket-Protocol"-header) protocol und dem angegebenen pinginterval. Wenn Alle Parameter sind ein einem request JSON-Objekt zu übergeben:
Üblicherweise weist man den Rückgabewert dieser Funktion einer Variablen zu: var websocket_var = websocket(...) um die weiter untenbeschriebenen Methoden aufrufen zu können.
websocket(configobj)

Bei dieser Variante werden alle Parameter in configobj übergeben. Damit sind weiterführende Optionen möglich. Die folgenden Felder sind unterstützt:

  • url: Die Websocket-URL (ws: oder wss:)
  • protocol: Das Subprotokoll ("Sec-WebSocket-Protocol"-header)
  • pinginterval: das Ping-Intervall
  • headers : optionales JSON-Objekt, das zu sendende http-Header als Name/Wert-Paare enhält.

Üblicherweise weist man den Rückgabewert dieser Funktion einer Variablen zu: var websocket_var = websocket(...) um die weiter untenbeschriebenen Methoden aufrufen zu können.

websocket_var.message()
Gibt die letzte auf dem Socket empfangene Websocket-Nachricht zurück. Das Ergebnis ist eine Ereignisquelle und kann in on()-Anweisungen als Trigger-Bedingung verwendet werden und kann auch await()-ed werden
websocket_var.send(message [, opcode])
sendet message als Websocket-Message. Wenn opcode nicht angegeben wird, wird die message als "text" (opcode 1) versendet.
websocket_var.close([closecode [, reason]])
schliesst den Websocket mit dem close-code "Normal" (1000), oder dem angegebenen closecode. Wenn angegeben, wird reason in der close-message mitgesendet.
writefile(filename, irgendwas [, append])
konvertiert irgendwas in einen String, und schreibt das Resultat als File filename. Wenn irgendwas == null ist, wird filename gelöscht. Wenn append auf true gesetzt ist, wird irgendwas am Ende des Files angehängt, wenn es schon existiert, ansonsten wird ein schon existierendes File überschrieben.

Hinweis

Um Pfade für filename zu verwenden, muss der Userlevel >=2 sein (Standard-Userlevel für Produktionsgeräte ist 0). Andernfalls können Files nur in das p44script Datenverzeichnis geschrieben werden, oder wenn der Pfad mit "_/" beginnt, ins p44script-Temporärverzeichnis.

Steuerung von geräte-/produkt­spezifischen Subsystemen

Hinweis - Produktspezifische Features

Die in den folgenden Abschnitten beschriebenen Features sind abhängig vom jeweiligen Gerätetyp, insbesondere die Ansteuerung von externer Hardware über GPIO-Anschlüsse, welche speziell dafür ausgerüstete Gerätevarianten braucht (z.B. den LED-Controller P44-LC-LED, oder den Automationscontroller P44-AC-DCM), oder dann DIY-Aufbauten wie das P44-DSB-X-Image auf Raspberry Pi.

P44-LC: Funktionen zur Verwendung in Trigger-Aktionen oder globalen Skripten

scene(name [, transition_time])
Aufruf der Szene durch name, mit optionaler transition_time in Sekunden
scene(id, zone_or_device [, transition_time])
Aufruf der Lichtszene durch id (numerische digitalSTROM-Szene oder generischer Name wie 'preset 1') in zone (Raum/Zone nach Name), mit optionaler transition_time in Sekunden
scene(id, zone_or_device, transition_time, group)
in der Gruppe group ('light', 'shadow', 'heating'...) die Szene nach id (numerische digitalSTROM-Szene oder generischer Name wie 'preset 1') in zone_or_device (in Raum/Zone nach Name oder in einem einzelnen Gerät nach Name oder dSUID) aufrufen, mit optionaler transition_time in Sekunden
sceneid(name)
gibt die id der Szene namens name (als generischen Preset-Namen wie etwa 'preset 1') zurück, oder null wenn keine solche Szene existiert.
set(zone_or_device, value [, transition_time])
Helligkeitswert eines Raums/einer Zone oder eines einzelnen Geräts (nach Name oder dSUID) auf value (0..100) setzen, mit optionaler transition_time in Sekunden
set(zone_or_device, value, transition_time, channelid)
setzt den durch channelid angegebenen Kanal ('hue', 'saturation', 'hPos'...... - Hinweis: channelIDs sind case-sensitive!) auf value, in Raum/Zone oder in einem einzelnen Gerät (nach Name oder dSUID), mit transition_time in Sekunden
trigger(triggername)
führt die Aktion des Triggers mit dem Namen triggername aus.
savescene(name)
savescene(id, zone [, group])
speichert die Szene nach name oder nach id, zone und group (Standardgruppe ist 'light')

P44-DSB/P44-LC: Zugriff auf Geräte und API

Geräteebene

Hinweis: Die folgenden Funktionen sind in Skripten auf Geräteebene verfügbar (z. B. in Szenenskripten). Aber grundsätzlich sind diese Funktionen Mitglieder des Geräteobjekts oder eines seiner Mitglieder. Ein Geräteobjekt kann auch von globalen Skripten mit der Funktion device gefunden werden, siehe unten. Dies ermöglicht Anweisungen wie: device('mydevicename').output.channel('brightness',75)

output
Stellt den Ausgang eines Geräts dar (bei Geräten ohne Ausgang ist dies undefiniert).
output.applychannels([force [, transitionTimeOverride]])
übernimmt Änderungen an Kanälen, die mit dimchannel und channel vorgenommen wurden. Wenn force wahr ist, werden auch unveränderte Kanäle wieder auf die Hardware angewandt. Wenn transitionTimeOverride gesetzt ist, werden die Übergangszeiten aller sich ändernden Kanäle mit dem angegebenen Wert überschrieben. Ansonsten gelten die Übergangszeiten, wie sie mit loadscene aus einer Szene geladen oder mit channel individuell eingestellt wurden.
output.syncchannels()
erzwingt das Rücklesen der aktuellen Kanalwerte aus der Hardware.
output.channel(channelid)
gibt den aktuellen Wert von channelid zurück ('brightness', 'hue', 'saturation', 'ct', 'hPos' - Hinweis: channelIDs sind case sensitive!)
Bitte beachten, dass Kanäle Unterfelder haben mit den Namen .valid (true, wenn der Kanal mit der Hardware synchronisiert ist), .age (Sekunden seit der letzten Änderung) und .oplevel (ein Wert zwischen 0..100, der den allgemeinen "Gesundheitszustand" des Geräts angibt, zu dem der Kanal gehört, was Funkempfang, Batteriestand usw. umfasst). Ein Kanal ist eine Ereignisquelle und kann in on()-Anweisungen als Triggerbedingung verwendet werden und kann auch await()-ed werden.
output.channel(channelid, value[, transition_time])
Setzt den Wert von channelid auf value, mit optionaler transition_time in Sekunden.
Bitte beachten, dass die Änderung des Kanalwerts nicht automatisch auf die Hardware angewendet wird; dazu muss applychannels() aufgerufen werden. Hinweis: channelIDs sind case sensitive!
output.dimchannel(channelid, valuechange, transition_time)
ändert den Wert von channelid um valuechange, mit optionaler transition_time in Sekunden. Hinweis: channelIDs sind case sensitive!
output.loadscene(sceneIdOrNo [, transitionTimeOverride])
lädt die Kanäle des Ausgangs mit den in der Szene sceneIdOrNo gespeicherten Werte. Die Szene wird durch ihre Nummer oder den Preset-Namen (z.B. 'bell 1' oder 'preset 2') bestimmt. Wenn transitionTimeOverride angegeben ist, werden die Überganszeiten aller Kanäle auf diesen Wert gesetzt, auch wenn die Szene andere Werte definiert.
Bitte beachten, dass die geladenen neuen Kanalwerte nicht automatisch auf die Hardware angewendet werden; dazu muss applychannels() aufgerufen werden. loadscene() kann z.B. dazu verwendet werden, eine Szene zu laden, aber vor der Anwendung auf die Ausgänge noch mit channel() zu justieren.
output.runactions(sceneIdOrNo)
führt die Szenen-Aktionen (z.B. Blinken, oder Start eines Szenenscripts) der Szene sceneIdOrNo auf. Die Szene wird durch ihre Nummer oder den Preset-Namen (z.B. 'bell 1' oder 'preset 2') bestimmt.
output.stopactions()
stoppt alle laufenden Szenen-Aktionen (Szenenscripts, Blinken, etc.)
sensor('id_or_index')
gibt den aktuellen Wert eines Sensoreingangs zurück. id_or_index kann entweder der Index des Sensors sein (beginnend bei 0), oder die Text-ID (eine Zeichenkette wie 'temperature' oder 'humidity', je nachdem, was das Gerät tatsächlich liefert)
Beachten Sie, dass Sensoren Unterfelder mit den Namen .valid (true, wenn der Sensor einen aktuellen Wert hat), .age (Sekunden seit der letzten Aktualisierung) und .oplevel (ein Wert zwischen 0..100, der den allgemeinen "Gesundheitszustand" des Sensors angibt, der Funkempfang, Batteriestand usw. umfasst) haben. Ein Sensor ist eine Ereignisquelle und kann in on()-Anweisungen als Triggerbedingung verwendet werden und kann auch await()-ed werden.
input('id_or_index')
gibt den aktuellen Wert eines binären Eingangs zurück. id_or_index kann entweder der Index des Binäreingangs sein (beginnend bei 0), oder die Text-ID (eine Zeichenkette wie 'rain' oder 'window_handle', je nachdem, was das Gerät tatsächlich bereitstellt). Die Eingangswerte sind normalerweise 0 oder 1, aber spezielle Eingänge wie Fenstergriffe können mehrere Zustände haben (2,3...).
Beachten Sie, dass Eingänge Unterfelder mit den Namen .valid (true, wenn der Zustand des Eingangs bekannt ist), .age (Sekunden seit der letzten Aktualisierung) und .oplevel (ein Wert zwischen 0..100, der den allgemeinen "Gesundheitszustand" des Eingangs angibt, der den Funkempfang, den Batteriestand usw. einschließt) haben. Ein Eingang ist eine Ereignisquelle und kann in on()-Anweisungen als Triggerbedingung verwendet werden und kann auch await()-ed werden.
button('id_or_index')
gibt den aktuellen Wert eines Tasters zurück. id_or_index kann entweder der Index des Tasters sein (beginnend bei 0), oder die Text-ID (eine Zeichenkette wie 'up' oder 'down', je nach Art des Tasters). Der Wert repräsentiert die Anzahl der erkannten Klicks (1..4) bzw. >4, wenn die Schaltfläche gedrückt gehalten wird.
Beachten Sie, dass Taster Unterfelder mit den Namen .valid (true, wenn der Zustand der Schaltfläche bekannt ist), .age (Sekunden seit der letzten Betätigung der Schaltfläche) und .oplevel (ein Wert zwischen 0..100, der den allgemeinen "Gesundheitszustand" des Tasters angibt, der den Funkempfang, den Batteriestand usw. umfasst) haben. Ein Taster ist eine Ereignisquelle und kann in on()-Anweisungen als Triggerbedingung verwendet werden und kann auch await()-ed werden.
view
Nur P44-DSB-X, P44-LC-E+L, P44-LC-LED mit WS281x Ledchains: Zugriff auf die Root-Ansicht eines Ledchain-Geräts. Das zurückgegebene Objekt ist eine P44lgrView, die über eigene Funktionen zur (Re)Konfiguration und zum Auffinden von Ansichten in ihrer Ansichtshierarchie verfügt

Globale Ebene

Hinweis: Diese globalen Funktionen ermöglichen den Zugriff auf bestimmte Geräte im P44-DSB/P44-LC direkt oder indirekt über die vDC-API. Diese können für fortgeschrittene benutzerdefinierte Anwendungen benötigt werden, z. B. für komplexe Effekt-Setups, die eine koordinierte Steuerung mehrerer Geräte erfordern, normalerweise von einem globalen Hauptskript aus. Für Skripte, die sich auf ein einzelnes Gerät beziehen, ist die Verwendung von Skripten auf Geräteebene, wie z. B. das Szenenskript, vorzuziehen. Bitte seien Sie vorsichtig, wenn Sie direkt auf Geräte und API zugreifen.

device('devicename')
device('dSUID')
Zugriff auf ein Gerät über den devicename oder die dSUID. Beachten Sie, dass die Verwendung von Namen zwar bequemer ist, Skripte aber möglicherweise abbrechen, wenn Benutzer Geräte umbenennen. Daher wird die Verwendung von dSUID für Skripte empfohlen, die lange Zeit installiert bleiben und funktionieren sollen
valuesource('valuesource_id')
findet eine valuesource (Quelle von Werten, die on(xxx) Ausdrücke oder Auswertebedingungen auslösen können) anhand ihrer internen ID. Beachten Sie, dass es in der Regel besser ist, auf diese Werte mit device(x).sensor(y) zuzugreifen.
vdcapi(json_request)
Gibt einen vDC-API-Methodenaufruf oder eine Benachrichtigung aus. Gibt die Antwort der Methode oder nur ein leeres Ergebnis für eine Benachrichtigung zurück
webrequest()
Gibt den letzten JSON-Request an den scriptapi-Endpoint der JSON-API zurück. webrequest ist eine Eventquelle und kann z.B. mit on(webrequest()) as request { ... } verwendet werden, um API-Kommandos in Scripten zu implementieren. Der Returnwert von webrequest() hat die Methode answer() um den Request zu beantworten. Der ganze Mechanismus kann verwendet werden, wenn neben der Standard-Weboberfläche kundenspezifische Spezialwebseiten implementiert werden sollen.
request.answer(json_oder_error)
Beantwortet einen Web-Request (im Beispiel oben die Variable request) mit einer JSON-Antwort oder einem Fehler. Üblicherweise wird eine Antwort als Teil eines on() Handlers gesendet, mit einer Konstruktion wie z.B.:
on (webrequest()) as request {
  // request ausführen
  // ...
  request.answer({ "status": "alles ok"});
}

LED-Ketten: p44 low resolution graphics (p44lrgraphics) Zugriff

p44lrgraphics ist ein Graphik-Subsystem speziell für Smart-LEDs. Hier wird nur das p44script-Interface dazu beschrieben. Mehr Informationen dazu findet sich in der technischen Dokumentation online.

lrg
liefert den Rootview der gesamten, aktuell konfigurierten LED-Ketten-Anordnung, d.h. die Ansicht, die den gesamten Bereich enthält, der von allen gemappten LED-Ketten-Segmenten abgedeckt wird.
addledchain(ledchainconfigstring)
fügt eine LED-Kette zur LED-Kettenanordnung hinzu. ledchainconfigstring hat das gleiche Format wie der Kommandozeilenparameter --ledchain:
[LED-Typ:[ledGerätename:]]AnzahlLEDs:[x:dx:y:dy:ersterOffset:offsetDazwischen][XYSA][W#Weisston]
removeledchains()
entfernt alle ledchains aus der LED-Kettenanordnung
ledchaincover()
gibt den rechteckigen Bereich (x,y,dx,dy) zurück, der aktuell (evtl. teilweise) von den installierten ledchains abgedeckt wird
neededledpower()
gibt die (ungefähre) elektrische Leistung in Milliwatt zurück, die für die aktuell angezeigten Pixel der LED-Ketten-Anordnung benötigt wird.
Beachten Sie, dass dies die Leistung zurückgibt, die benötigt würde, um alle Pixel ohne Begrenzung anzuzeigen (auch wenn sie aktuell begrenzt ist, siehe setmaxledpower())
currentledpower()
Gibt die (ungefähre) elektrische Leistung in Milliwatt zurück, die für die aktuell angezeigten Pixel tatsächlich verbraucht wird. Diese sollte den mit setmaxledpower() eingestellten Wert nicht wesentlich überschreiten.
setmaxledpower(maxpower)
Setzt die (ungefähre) maximale elektrische Leistung in Milliwatt, die die gesamte LED-Kettenanordnung verbrauchen darf. Wenn die aktuell angeforderten Pixelfarben das Limit überschreiten würden, werden alle Pixel nach Bedarf gedimmt, um das Leistungslimit nicht zu überschreiten
setledrefresh(refreshinterval [, priorityinterval])
Setzt das minimale Refresh-Interval für die angeschlossenen LED-Ketten, d.h. wie oft maximal ein neuer Zustand auf die LEDs ausgegeben wird. Mit steigender Anzahl LEDs pro Kette muss dieses Interval u.U. grösser gewählt werden, damit alle LEDs angesteuert werden können (Default is 15mS). Das optionale priorityinterval gibt an, wie lange prioritäres Timing (z.B. Scrolling) Vorrang gegenüber sekundärem Timing (etwa in sich animierte Bestandteile eines gescrollten Bereichs) haben. Das kann wichtig sein für ruckelfreie Laufschriften etc. (Default ist 50mS).
setrootview(newrootview)
Setzt newrootview als neuen root view.
makeview(json)
makeview(resource_file)
erzeugt einen View entsprechend der Konfiguration aus dem direkt angegebenen json oder aus einem resource_file gelesenen JSON-text.
findview(viewlabel)
sucht nach einem Subview mit dem angegebenen viewlabel, gibt den View oder undefined zurück
addview(view)
fügt view als Subview hinzu (wenn dieser View Subviews unterstützt)
parent()
gibt den übergeordneten View zurück (oder null, wenn keiner vorhanden ist)
remove()
entfernt den View von seinem übergeordneten View (wenn es einen übergeordnete View gibt), gibt true zurück, wenn der View entfernt werden konnte.
.configure(json)
.configure(resource_file)
(re)konfiguriert den View mit dem direkt angegebenen json oder mit einem resource_file gelesenen JSON-text.
.set('propertyname', new_value)
Setzt eine einzelne Eigenschaft des Views. Dies ist einfach ein bequemerer Weg als die Verwendung von configure mit einem json-Objekt, das ein einzelnes Feld enthält, bewirkt aber technisch gesehen das Gleiche.
.animator('propertyname')
Ermittelt einen Animator für die angegebene Eigenschaft der Ansicht. Animierbare p44lrg-Eigenschaften sind: alpha, rotation, x, y, dx, dy, content_x, content_y, rel_content_x, rel_content_y, rel_center_x, rel_center_y, content_dx, content_dy, color, bgcolor. Farben haben die animierbaren Unterkomponenten r,g,b,a,hue,saturation,brightness
Wenn ein gültiger animierbarer Eigenschaftsname übergeben wird, wird ein animator-Objekt zurückgegeben. Siehe Animator-Beschreibung für Details
.stopanimations()
Stoppt alle in der Ansicht laufenden Animationen
hsv(hue [, saturation [, brightness]])
konvertiert die angegebenen Werte hue (0..359), saturation (0..1) und brightness (0..1) in das hexadezimale 6-stellige Web-Farbformat, das zum Setzen von bgcolor oder color in p44lrg-Ansichten verwendet werden kann. saturation (0..1) und brightness stehen standardmäßig auf 1, wenn sie nicht angegeben werden.

Animators

Animatoren erzeugen eine Reihe von Änderungen eines numerischen Wertes über die Zeit, mit einer Reihe von Parametern wie Gesamtdauer, zu verfolgende Kurve (Funktion), Wiederholung, Verzögerung usw. Animatoren werden von animator(...)-Funktionen von Objekten zurückgegeben, die Animation unterstützen, wie z. B. p44lrg-Ansichten oder PWM/analoge Ausgänge.

Die Animator-Methoden, die nur einen Parameter setzen, geben den Animator selbst zurück, so dass Aufrufe wie animator('dx').delay(2).function('easein',4).runto(50,0:01:02) verkettet werden können. Animationen laufen gleichzeitig mit dem Skript, das sie startet, aber await() kann verwendet werden, um auf das Ende einer Animation zu warten.

.delay(Sekunden)
verzögert den Start der Animation um die angegebene Zeit
.runafter(animation)
startet die Animation erst, nachdem die angegebene animation beendet ist
.repeat(cycles [, autoreverse])
Bewirkt, dass die Animation insgesamt cycles mal wiederholt wird. Wenn cycles auf 0 gesetzt ist, wird die Animation für immer wiederholt (bis sie explizit mit stop() gestoppt wird). Wenn autoreverse true ist, wird die Animation jeden zweiten Zyklus rückwärts ausgeführt.
.function('animationfunction')
Setzt die Animationsfunktion, die eine der folgenden sein kann: linear,easein,easeout,easeinout
.from(startvalue)
Legt den Startwert für die Animation fest. Standardmäßig ist der Startwert der aktuelle Wert der zu animierenden Eigenschaft, aber in einigen Fällen ist dieser nicht zum Auslesen verfügbar (z.B. Farbton oder Sättigung eines ausgeschalteten RGB-Lichts ist undefiniert), daher erlaubt from, einen Startwert explizit zu setzen.
.step(minsteptime [, stepsize])
Hiermit kann die Auflösung der Animation beeinflusst werden. Dabei gibt minsteptime die minimale Zeit in Sekunden zwischen zwei Änderungen des animierten Werts an (0 = Standard für die jeweilige Hardware verwenden) und stepsize die Grösse der Schritte auf dem animierten Wert (0 = automatisch entsprechend minsteptime)
.runto(endvalue, duration)
Nur diese Methode startet tatsächlich die Animation, um endvalue innerhalb der angegebenen duration zu erreichen.
Normalerweise sieht eine Anweisung zum Einrichten einer Animation so aus: animator('color.hue').delay(2).from(0).runto(360,20), wobei runto die letzte Methode in der Kette ist.
runto kann auch mehrmals aufgerufen werden, ohne die anderen Animationsparameter neu zu setzen zu müssen (ausgenommen runafter und delay, sowie from).
.reset()
Setzt die Animation auf ihre Standardwerte zurück (und stoppt sie vorher, falls sie gerade noch läuft)
.stop()
Hält eine Animation an
.current
gibt den aktuellen Wert des Animators zurück

Digital I/O (Signale und Indikatoren)

p44script kann verschiedene Hardware als digitale Ein- oder Ausgänge verwenden. Die Hardware wird über einen pinspec-String definiert wie folgt:

gpio.11
GPIO Nummer 11
led.ledname
System-LED mit dem Namen ledname
i2c0.MCP23017@22.7

Pin #7 eines i2c-I/O-Expander-Chips MCP23017, auf i2c-Adresse 0x22, an i2c-Bus Nummer 0. Unterstützte Chips sind TCA9555, PCF8574, MCP23017

spi12.MCP23S17@0.6
Pin #5 eines SPI-I/O-Expander-Chips MCP23S17, am SPI-Bus 1.2 (Bus 1, Chip Select 2)

Der pinspec für digitale Eingänge kann ein / vorangestellt werden, um die Signalpolarität zu invertieren, sowie ein + oder ein - um an einem Eingang einen Pullup bzw. Pulldown zu aktivieren (sofern die Hardware das unterstützt):

+/gpio.22
GPIO Nummer 22 mit aktiviertem Pullup, und invertierter Signalpolarität (z.B. für einen Endschalter, der den Eingang mit GND verbindet, wenn er aktiv ist).

Bitte Vorsicht - Hardwarezugriff

Diese Funktionen bieten Zugriff auf die Hardware und können bei unsachgemässer Verwendung deshalb Fehlfunktionen und je nach angeschlossenen Geräten auch Schäden verursachen. Die Verwendung dieser Funktionen setzt daher mindestens userlevel 1 voraus.

Funktionen für digitale Ein/Ausgänge

var d = digitalio(pinspec, Ausgang [, Initialzustand])
Erzeugt ein Objekt zur Ansteuerung eines digitalen Eingangs- (Ausgang=false) oder Ausgangssignals (Ausgang=true) gemäss pinspec. Mit Initialzustand wird der initiale Zustand festgelegt. Bei Eingängen spielt Initialzustand als erwarteter Ruhezustand eine Rolle, wenn Änderungen am Zustand einen Event auslösen sollen (nicht aber das Einrichten des Eingangs).

Das von digitalio() zurückgegebene Objekt hat folgende Methoden (d = mit digitalio erzeugtes Objekt):

d.toggle()
Für Ausgänge: ändert den Ausgangszustand auf das Gegenteil des aktuellen Zustands.
d.state()
Gibt den aktuellen Zustand des Signals zurück. Wenn ein Einganssignal mit detectchanges() auf Signaländerungsüberwachung eingestellt ist, ist state() eine Ereignisquelle und kann in on(...) {...}-Handlern als Auslöser verwendet werden.
d.state(newstate)
Setzt ein Ausgangssignal auf den Wert newstate.
d.detectchanges([Entprellungszeit [, Pollintervall]])
d.detectchanges(null)
Schaltet die Signaländerungsüberwachung ein oder aus. Beim Einschalten kann optional die Entprellungszeit und (für Eingänge, deren Hardware nicht von sich aus Signaländerungen erkennt) das Pollinterval eingestellt werden. Mit eingeschalteter Signalüberwachung kann state() in on(...) {...}-Handlern in der Auslösebedingung verwendet werden.

Funktionen für Indikatoren

Ein Indikator ist ein Ausgang, der üblicherweise zur optischen Signalisation an den User benutzt wird (also meist eine LED), und dazu einige Komfortfunktionen für die üblichen Anwendungsfälle wie kurzes Aufleuchten oder Blinken zur Verfügung stellt.

var i = indicator(pinspec [, initialValue])
Erzeugt ein Objekt zur Ansteuerung eines digitalen Ausgangs gemäss pinspec, der als Indikator genutzt werden soll.

Das von indicator() zurückgegebene Objekt hat folgende Methoden (i = mit indicator erzeugtes Objekt):

i.on()
i.on(Einschaltdauer)
schaltet den Indikator ein. Wenn eine Einschaltdauer angegeben wird, schaltet der Indikator nach der angegeben Zeit automatisch wieder aus. Die on()-Methode wartet aber die Einschaltdauer nicht ab; der Indikator läuft parallel im Hintergrund.
i.off()
schaltet den Indikator aus (und stoppt allfälliges Blinken)
i.blink([Periode [, ProzentEin [, Dauer]]])
Lässt den Indikator mit der Periode blinken, wobei ProzentEin das Tastverhältnis des Blinkens angibt (z.B. 20 = 20% ein und 80% aus). Wenn die Dauer angegeben wird, stoppt das Blinken automatisch. Das Blinken läuft parallel im Hintergrund.
i.stop()
stoppt das Blinken im gerade aktiven Zustand

Analog I/O

p44script kann verschiedene Hardware als analoge Ein- oder Ausgänge verwenden. Die Hardware wird über einen pinspec-String definiert wie folgt:

pwmchip0.1
PWM-Signal-Ausgang Nummer 1 an PWMChip Nummer 0, mit Default-PWM-Periode
pwmchip0.2.100000
PWM-Signal-Ausgang Nummer 2 an PWMChip Nummer 0, mit PWM-Periode von 100000nS (= 0.1mS, = 10kHz)

Bitte beachten: Hardware-Limitationen

Je nach PWM-Hardware sind die möglichen Werte für die PWM-Periode unterschiedlich, und möglicherweise nicht für jeden Ausgang einzeln einstellbar.

i2c0.MAX1161x@33.2
Eingang #2 eines i2c-A/D-Wandlers vom Typ MAX1161x, auf i2c-Adresse 0x33, an i2c-Bus Nummer 0. Aktuell unterstützte Chips sind MAX11612..617, MCP3021 sowie der Temperatursensor LM75.
spi12.MCP3008@0.6
Eingang #6 eines SPI-A/D-Wandlers vom Typ MCP3008 am SPI-Bus 1.2 (Bus 1, Chip Select 2). Aktuell unterstütze Chips sind MCP3008 und MCP3002.

Bitte Vorsicht - Hardwarezugriff

Diese Funktionen bieten Zugriff auf die Hardware und können bei unsachgemässer Verwendung deshalb Fehlfunktionen und je nach angeschlossenen Geräten auch Schäden verursachen. Die Verwendung dieser Funktionen setzt daher mindestens userlevel 1 voraus.

Funktionen für analoge Ein/Ausgänge

var a = analogio(pinspec, Ausgang [, Initialwert])
Erzeugt ein Objekt zur Ansteuerung eines analogen Eingangs- (Ausgang=false) oder Ausgangssignals (Ausgang=true) gemäss pinspec. Mit Initialwert wird der initiale Wert festgelegt.

Das von analogio() zurückgegebene Objekt hat folgende Methoden (a = mit analogio erzeugtes Objekt):

a.value()
Liest den aktuellen Aanlog-Wert des Eingangs (bzw den aktuell eingestellten Wert bei Ausgängen). Wenn ein Analogeingang mit poll() auf regelmässig Abfrage eingestellt ist, ist _value() eine Ereignisquelle und kann in on(...) {...}-Handlern als Auslöser verwendet werden.
a.value(val)
nur für Ausgänge: setzt den Ausgangswert auf val. Der mögliche Wertebereich kann mit range ausgelesen werden.
a.range()
Gibt den Wertebereich für das Analogsignal, und wenn bekannt, die Auflösung als Objekt mit den Feldern min, max und ggf. resolution zurück.
a.poll(Intervall [, Toleranz])
a.poll()
richtet eine regelmässige Abfrage eines Analogeingangs mit angegebenem Intervall (und ggf. Toleranz) ein. Mit eingeschalteter regelmässiger Abfrage kann value() in on(...) {...}-Handlern in der Auslösebedingung verwendet werden. _poll() ohne Parameter schaltet die regelmässige Abfrage aus.
a.filter(Typ, [Intervall [, Sammelzeit]])
installiert einen Filter Typ ("average", "simpleaverage", "min", "max"), der die gelesenen Werte über das angegebene Intervall mit einem "sliding window" filtert. Die Sammelzeit gibt das Zeitfenster pro Datenpunkt an. Die Filterfunktion "average" berücksichtigt auch unregelmässige Zeitabstände zwischen den Datenpunkten, "simpleaverage" nicht.
a.animator()
gibt einen Animator zurück, mit dem der Wert eines Analogausgangs über die Zeit animiert werden kann.

DC-Motoren

Das DC-Motor-Objekt kann einen Analogausgang für den Motor-Power (meist PWM), ein oder zwei Digitalausgänge für die Kontrolle der Drehrichtung und bei geeigneter Hardware auch Umschaltung von Fahren/Bremsen, einen Analogeingang für die Überwachung des Motorstroms für Abschaltung bei Überlast, und schliesslich 2 Digitaleingänge für Endschalter zu einer komfortablen Motoransteuerung kombinieren.

var m = dcmotor(Ausgang [, Richtung1 [, Richtung2 ]])
Erzeugt ein dcmotor-Objekt. Die Parameter können entweder schon vorher erzeugte I/O-Objekte sein, oder pinspec-Strings um die entsprechenden Signale direkt zu erzeugen. Ausgang muss ein analoger Ausgang sein, üblicherweise ein PWM, der die Motorleistung regelt. Für einen Motor mit nur einer Laufrichtung müssen keine weiteren Signale angegeben werden. Wenn der Motor (über eine H-Brücke) in beide Richtungen laufen kann, dann gibt entweder Richtung1 allein die Drehrichtung an, oder - wenn auch Richtung2 angegeben ist - steuert Richtung1 die eine Seite und Richtung2 die andere Seite der H-Brücke. In dieser Konfiguration ist dann auch aktives Bremsen und Halten des Motors möglich (beide Seiten der H-Brücke gleichgeschaltet).

Das von dcmotor() zurückgegebene Objekt hat folgende Methoden (m = mit dcmotor erzeugtes Objekt):

m.outputparams(Skalierung [, Offset])
Wenn der Ausgang für die Motorleistung nicht den Wertebereich 0..100 hat (was nur bei PWMs normalerweise der Fall ist), kann die Umsetzung der 0..100 Leistungsangabe in den effektiven Ausgangswert angepasst werden. Standardmässig ist Skalierung = 1 und Offset = 0.
m.power(Power [, Drehrichtung [, Rampenzeit [, Rampenexponent]]])
Verändert die Motorleistung auf Power (Wertebereich 0..100%). Drehrichtung kann 1 (default, vorwärts), -1 (rückwärts) oder 0 (bremsen) sein. Eine positive Rampenzeit gibt die Zeitdauer an, während der die Veränderung erfolgen soll. Eine negative Rampenzeit gibt die Zeitdauer für eine 0..100-Rampe an, die effektive Zeit wird proportional zur Veränderung bestimmt (kleine Leistungsänderung gibt kürzere Rampe). Standardmässig wird die Rampenzeit -1 (also 1 Sekunde für eine 0..100-Änderung) verwendet.
m.stop()
Schaltet die Leistung ohne Verzögerung auf 0. Der Motor stoppt und läuft aus. Um zu bremsen, kann stattdessen z.B. m.power(50,0) verwendet werden (Bremsen mit 50% Leistung).
m.status()
Gibt den Status des Motors als Objekt mit den Feldern power, direction und falls ein Stromsensor konfiguriert ist, current zurück. Wenn der Motor von einem Endschalter oder der Strombegrenzung gestoppt wurde, gibt ein zusätzliches Feld stoppedby das an (enthält entweder "overcurrent" oder "endswitch"). status() ist eine Ereignisquelle und kann in on(...) {...}-Handlern als Auslöser verwendet werden. Der Status wird als Ereignis ausgelöst, wenn eine mit power() gestartete Rampe ihren Endwert erreicht hat, oder wenn der Motor von Endschaltern oder Strombegrenzung gestoppt wird.
m.endswitches(PositivesEnde, NegativesEnde [, Entprellungszeit [, Pollinterval]])
Definiert zwei digitale Eingänge (PositivesEnde, NegativesEnde, entweder als digitalIO-Objekt oder als pinspec) als Endschalter für die Endanschläge des Antriebs. Optional kann die Entprellungszeit und (für Eingänge, deren Hardware nicht von sich aus Signaländerungen erkennt) das Pollinterval eingestellt werden.
Wenn ein Endschalter anspricht, wird der Motor auf jeden Fall gestoppt, auch wenn er eigentlich in die Richtung des anderen Endschalters läuft (sichert die Mechanik bei falsch herum angeschlossenem Motor). Damit der Motor aber aus dem Endschalter wegbewegt werden kann, wird power() nur jeweils in die Richtung zum aktiven Endschalter hin blockiert, aber es ist möglich den Motor in die andere Richtung zu starten.
m.currentsensor(Sensor [, Abfrageintervall])
m.currentsensor(null)
Definiert (oder entfernt, wenn Sensor null ist) einen analogen Eingang Sensor als Motorstrom-Sensor, mit dem angegebenen Abfrageintervall. Wird kein Abfrageintervall angegeben, erfolgt die Abfrage 3 mal pro Sekunde.
m.currentlimit(Limit [, Anfahrzeit [, MaxAnfahrstrom]])
Setzt die Strombegrenzung auf Limit. Der Wert ist nicht in A oder mA, sondern einfach der Wert wie ihn der Analogeingang zurückliefert (üblicherweise ein roher A/D-Wert, z.B. 0..4095 bei einem MAX11615). Wenn dieser Wert überschritten wird, stoppt der Motor. Da beim Anfahren u.U. ein höherer Strom benötigt wird als während der Fahrt, kann mit Anfahrzeit eine Dauer nach der Ausführung eines power()-Befehls angegeben werden, in der erlaubte Strom bis MaxAnfahrstrom gehen darf.

P44features - spezifische Funktionalität/Hardware-Unterstützung

Die folgenden Funktionen sind globale Funktionen, die den Zugriff auf "Features" (siehe hier für Details) und deren API von Skripten aus ermöglichen. P44features sind eine Bibliothek spezifischer Funktionalitäten, die in der Regel von plan44 für einen bestimmten Ausstellungs-/Kunst-Anwendungsfall entwickelt wurden (Beispiele siehe hier). Da einige dieser Funktionen auch für andere Anwendungen nützlich sein können, sind sie in einigen P44-XX-Produkten für die Verwendung mit p44script enthalten.

feature(name)
Zugriff auf ein Merkmal über Name. Jedes Feature unterstützt einige allgemeine Methoden, wie unten gezeigt, und eine Reihe von Befehlen und Eigenschaften, die spezifisch für das Feature sind.
featurecall(json_request)
Gibt json_request als eine Feature-API-Anfrage aus und gibt deren Antwort zurück (oder null, wenn der Aufruf keine Antwort hat). Das bedeutet, dass json_request auf die gleiche Weise verarbeitet wird, wie wenn es von einem Feature-API-Client über TCP gesendet wird. Ein Feature-API-Client ist eine externe Instanz, die über eine TCP-Socket-Verbindung auf die Feature-API zugreift, in der Regel ein System, das große Installationen, die aus vielen P44-xx-Modulen bestehen koordiniert.
featureevent(json_event)`
Sendet einen Event an den aktuellen Feature-API-Client (falls vorhanden). Mit featureevent() kann ein Gerät den API-Client (das koordinierende System) über lokale Ereignisse wie aktivierte Sensoren usw. informieren.
featureevent()
gibt Events (in JSON) zurück, die von aktiven Features ausgegeben werden, wie z. B. erkannte RFID, Eingabeänderungen usw. featureevent() kann an await() übergeben oder in on (f.featureevent()) as event { do something with event }-Handlern verwendet werden. Zu beachten ist, dass die Ereignisse auch an einen verbundenen API-Client gesendet werden, falls vorhanden.

Das Folgende sind Methoden des Feature-Objekts (siehe feature(...) oben). Für die folgenden Beispiele wird angenommen, dass das feature einer Variablen f zugewiesen ist.

f.status()
gibt den Status des Merkmals zurück. Ist false, wenn das Feature nicht initialisiert ist, oder wenn initialisiert, ein Feature-spezifischer JSON-Wert oder ein Objekt.

f.init(init_json) initialisiert das Feature mit feature-spezifischen init_json Parametern. Einige einfache Features können keine Parameter haben, für diese können Sie true als init_json übergeben.

f.cmd(Befehl [, json_param_object])
sendet command an die Funktion, mit optionalem json_param_object, das Befehlsparameter enthält.
f.set(property, value)
setzt ein einzelnes property im Merkmal auf einen neuen Wert value.