Der Block Script (JavaScript) führt Ihren Code für jede Nachricht aus. Verwenden Sie ihn, wenn die übrigen Blöcke nicht ausdrücken können, was Sie brauchen: Decodieren eines ungewöhnlichen Binärformats, Durchlaufen einer Liste, Erstellen eines komplexen Objekts. Bevorzugen Sie die fertigen Blöcke, wenn sie passen: Sie sind leichter zu lesen, benötigen kein Script-Kontingent und laufen schneller.
Einstellungen
| Einstellung | Bedeutung | Standard | Werte |
|---|---|---|---|
| code | Das Script | ein Beispiel | erforderlich; bis zu 64 KiB |
| Ausgänge | Anzahl der Ausgänge | 1 | 1 bis 4 (o0 bis o3) |
| labels | Ausgabenamen, durch Kommas getrennt | leer | Buchstaben, Ziffern, _, Leerzeichen und -; einer pro Ausgang, alle verschieden |
Jeder Script-Block in einem bereitgestellten Flow zählt auf das Kontingent Ihres Tarifs für Script-Blöcke (3, 6 oder 29 je nach IoT-Stufe). Eine Bereitstellung, die ein Script enthält, ist eine Bereitstellung mit Code-Risiko: Sie verlangt, dass der Name des Flows eingetippt wird, und wird protokolliert („Script changed“).
Was der Code sieht
Der Editor zeigt die Signatur über dem Codefeld: msg, node, context, flow, global, env → return msg | [a, b] | [[a, b]] | "label" | nothing.
| Name | Was es ist |
|---|---|
msg | Die Nachricht, eine Kopie, die Sie ändern dürfen. msg.metadata ist beschreibbar, außer den Systemfeldern; msg.msgType und msg.originator sind schreibgeschützt. |
node.send(msg) | Sendet eine Nachricht sofort auf Ausgang 1 (node.send([a, b]) wählt Ausgänge wie eine Rückgabe) |
node.status({ fill, shape, text }) | Der Status, der unter dem Block angezeigt wird |
node.warn(value), node.error(text) | Schreibt in das Protokoll des Blocks |
context.get("key"), context.set("key", value) | Ein Speicher dieses Blocks |
flow.get(…), flow.set(…) | Die Variablen des Flows, geteilt mit den Pfaden flow.* in anderen Blöcken |
global.get(…), global.set(…) | Die Variablen der Organisation (global.*) |
env.get(name) | Ein Umgebungswert |
console.log(value) | Dasselbe Protokoll wie node.warn |
Verwenden Sie den Schlüssel persist:name für den persistenten Speicher, zum Beispiel flow.set("persist:total", 12). Wird ein Schlüssel auf undefined gesetzt, wird er gelöscht.
Kontext-Schreibvorgänge werden angewendet, nachdem das Script gelaufen ist. Der erste Schreibvorgang über dem Limit eines Speichers stoppt die übrigen, und die Nachricht verlässt den Block über error mit limit; frühere Schreibvorgänge bleiben erhalten.
Was zurückgegeben werden darf
| Rückgabe | Wirkung |
|---|---|
return msg | Sendet die Nachricht auf Ausgang 1 |
return [a, b] | a auf Ausgang 1, b auf Ausgang 2 (bis zu 4); null sendet auf diesem Ausgang nichts |
return [[a, b]] | Beide auf Ausgang 1 |
return "alarm" | Die eingehende Nachricht auf dem Ausgang mit dem Label alarm |
Nichts (undefined, null, []) | Es wird nichts gesendet; die Nachricht endet hier |
Höchstens 64 Nachrichten pro Lauf. Ein neues Objekt wie return { payload: 1 } wird aus der Eingabe ergänzt; setzt es ein Engine-Feld auf einen anderen Wert, schlägt es mit readonly_field fehl.
Hilfsfunktionen
| Namensraum | Funktionen |
|---|---|
bytes | fromHex, toHex, fromBase64, toBase64, sha256, toText, fromText, readUint, readInt, readFloat, writeUint, writeInt, writeFloat; außerdem TextEncoder, TextDecoder |
num | round(value, digits), toHex(value, { bytes, bigEndian, prefix }) |
bits | fromBytes, fromInt, toInt, get |
obj | flatten(value, { separator, exclude, pathInKey }) |
time | parse, format, add, fields, mit Mustern wie yyyy-MM-dd HH:mm:ss und IANA-Zonen |
Nicht verfügbar: require, import(), eval, Function, fetch, Timer (verwenden Sie einen Block Delay), process, Buffer, WebAssembly. Das Script hat keinen Netzwerkzugriff, keine Dateien und keine Zugangsdaten. Date ist die echte Uhr.
Grenzwerte
| Grenzwert | Wert |
|---|---|
| CPU-Zeit pro Nachricht | 50 ms (Ihr Tarif erlaubt eventuell bis zu 200 ms) |
| Speicher | 32 MiB |
| Code | 64 KiB |
| Zurückgegebene Nachrichten | 64 |
| Nachrichtengröße, ein- und ausgehend | 256 KiB |
| übergebener Kontext | 64 KiB |
Drei Abbrüche in Folge (timeout oder memory) sperren das Script für 60 Sekunden: Nachrichten schlagen dann mit blocked fehl, ohne zu laufen. Die CPU-Zeit jedes Laufs zählt auf die monatliche Script-CPU auf der Nutzungskarte.
Fehler
Der Ausgang error enthält msg.error.code:
| Code | Bedeutung |
|---|---|
script | Der Code hat einen Fehler ausgelöst; line und col zeigen, wo |
timeout, memory | Über der CPU-Zeit oder dem Speicher |
limit | Mehr als 64 zurückgegebene Nachrichten oder ein Kontext-Schreibvorgang über seinem Limit |
msg_too_big | Eine Nachricht über 256 KiB |
unknown_label | Ein Label zurückgegeben, das kein Ausgang hat |
bad_return | Etwas zurückgegeben, das keine Nachricht, keine Liste und kein Label ist (oder ein Promise) |
readonly_field | msgType, originator oder ein Systemfeld geändert |
blocked | Nach drei Abbrüchen pausiert |
host_busy | Die Sandbox war nach einigen Versuchen weiterhin belegt |
script_unavailable | Der Script-Dienst ist nicht verfügbar |
Das Script testen
Script testen im Block-Panel führt den Code einmal in der echten Sandbox aus: „Nichts wird bereitgestellt; Speichern übernimmt den Code in den Block.“ Füllen Sie Payload (JSON), Metadata (JSON object), Message type, Originator type und Originator id aus, optional Context (optional JSON) als { "node": {…}, "flow": {…}, "global": {…} }, und wählen Sie Run. Das Ergebnis zeigt jeden Ausgang, das Protokoll, den geschriebenen Kontext und die CPU-Zeit. In den Block speichern behält den Code.
Beispiele
Ein 4-Byte-Float aus einer rohen Hex-Payload decodieren:
const data = bytes.fromHex(msg.payload.raw_hex);
msg.payload = { level_m: num.round(bytes.readFloat(data, 0, 4, { bigEndian: true }), 3) };
return msg;
Eine Nachricht mit einer Liste von Sensoren in je einen Messwert pro Sensorschlüssel aufteilen:
// in: { "sensors": [ { "id": "t1", "v": 21.5 }, { "id": "t2", "v": 19.0 } ] }
const out = {};
for (const s of msg.payload.sensors || []) out[`temp_${s.id}`] = s.v;
msg.payload = out; // { temp_t1: 21.5, temp_t2: 19 }
return msg;
Nach einer berechneten Klasse auf beschriftete Ausgänge leiten (Labels ok,warn,crit):
const t = msg.payload.temperature;
if (typeof t !== 'number') return null;
return t > 8 ? 'crit' : t > 6 ? 'warn' : 'ok';
Eine laufende Summe über Nachrichten hinweg führen:
const total = (flow.get('persist:litres_total') || 0) + (msg.payload.litres || 0);
flow.set('persist:litres_total', total);
msg.payload.litres_total = total;
return msg;
Wann man kein Script verwenden sollte
| Bedarf | Stattdessen verwenden |
|---|---|
| Eine Formel | Calculate |
| Schlüssel umbenennen, kopieren oder löschen | Change |
| Binäre Felder | Bytes |
| Verzweigung anhand eines Werts | Switch oder If / else |
| Verbrauch aus einem Zähler | Delta |
| Warten | Delay, Trigger, Timer |
Siehe Datentransformations-Blöcke und Flow-Limits.

