El bloque Script (JavaScript) ejecuta tu código en cada mensaje. Úsalo cuando los demás bloques no puedan expresar lo que necesitas: decodificar un formato binario poco habitual, recorrer una lista o construir un objeto complejo. Prefiere los bloques listos cuando encajen: son más fáciles de leer, no necesitan cupo de script y se ejecutan más rápido.
Ajustes
| Ajuste | Significado | Por defecto | Valores |
|---|---|---|---|
| code | El script | un ejemplo | obligatorio; hasta 64 KiB |
| salidas | Número de salidas | 1 | 1 a 4 (o0 a o3) |
| etiquetas | Nombres de salida, separados por comas | vacío | letras, dígitos, _, espacio y -; una por salida, todas distintas |
Cada bloque de script en un flujo desplegado cuenta para las Script blocks de tu plan (3, 6 o 29 según el nivel IoT). Un despliegue que contiene un script es un despliegue de riesgo Code: pide escribir el nombre del flujo y queda auditado («Script changed»).
Lo que ve el código
El editor muestra la firma sobre el campo de código: msg, node, context, flow, global, env → return msg | [a, b] | [[a, b]] | "label" | nothing.
| Nombre | Qué es |
|---|---|
msg | El mensaje, una copia que puedes modificar. msg.metadata es escribible salvo los campos del sistema; msg.msgType y msg.originator son de solo lectura. |
node.send(msg) | Envía un mensaje por la salida 1 de inmediato (node.send([a, b]) elige las salidas igual que un return) |
node.status({ fill, shape, text }) | El estado mostrado bajo el bloque |
node.warn(value), node.error(text) | Escribe en el registro del bloque |
context.get("key"), context.set("key", value) | Un almacén de este bloque |
flow.get(…), flow.set(…) | Las variables del flujo, compartidas con las rutas flow.* de otros bloques |
global.get(…), global.set(…) | Las variables de la organización (global.*) |
env.get(name) | Un valor del entorno |
console.log(value) | El mismo registro que node.warn |
Usa la clave persist:name para el almacén persistente, por ejemplo flow.set("persist:total", 12). Asignar una clave a undefined la elimina.
Las escrituras de contexto se aplican tras ejecutar el script. La primera escritura que supera el límite de un almacén detiene las demás, y el mensaje sale por error con limit; las escrituras anteriores se mantienen.
Qué puede devolver
| Return | Efecto |
|---|---|
return msg | Envía el mensaje por la salida 1 |
return [a, b] | a por la salida 1, b por la salida 2 (hasta 4); null no envía nada por esa salida |
return [[a, b]] | Ambos por la salida 1 |
return "alarm" | El mensaje entrante por la salida con la etiqueta alarm |
Nada (undefined, null, []) | No se envía nada; el mensaje termina aquí |
Como máximo 64 mensajes por ejecución. Un objeto nuevo, como return { payload: 1 }, se completa a partir de la entrada; si fija un campo del motor a otro valor, falla con readonly_field.
Auxiliares
| Espacio de nombres | Funciones |
|---|---|
bytes | fromHex, toHex, fromBase64, toBase64, sha256, toText, fromText, readUint, readInt, readFloat, writeUint, writeInt, writeFloat; también 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, con patrones como yyyy-MM-dd HH:mm:ss y zonas IANA |
No disponible: require, import(), eval, Function, fetch, temporizadores (usa un bloque Delay), process, Buffer, WebAssembly. El script no tiene red, ni archivos, ni credenciales. Date es el reloj real.
Límites
| Límite | Valor |
|---|---|
| Tiempo de CPU por mensaje | 50 ms (tu plan puede permitir hasta 200 ms) |
| Memoria | 32 MiB |
| Código | 64 KiB |
| Mensajes devueltos | 64 |
| Tamaño del mensaje, de entrada o de salida | 256 KiB |
| Contexto recibido | 64 KiB |
Tres interrupciones seguidas (timeout o memory) bloquean el script durante 60 segundos: los mensajes fallan entonces con blocked sin ejecutarse. El tiempo de CPU de cada ejecución cuenta para el Script CPU del mes en la tarjeta de uso.
Errores
La salida error incluye msg.error.code:
| Código | Significado |
|---|---|
script | El código lanzó una excepción; line y col indican dónde |
timeout, memory | Se superó el tiempo de CPU o la memoria |
limit | Más de 64 mensajes devueltos, o una escritura de contexto por encima de su límite |
msg_too_big | Un mensaje de más de 256 KiB |
unknown_label | Devolvió una etiqueta que ninguna salida tiene |
bad_return | Devolvió algo que no es un mensaje, una lista ni una etiqueta (o una promesa) |
readonly_field | Cambió msgType, originator o un campo del sistema |
blocked | Pausado tras tres interrupciones |
host_busy | El entorno de ejecución siguió ocupado tras varios intentos |
script_unavailable | El servicio de scripts no está disponible |
Probar el script
Test the script en el panel del bloque ejecuta el código una vez en el entorno real: «Nothing is deployed; Save puts the code into the block.» Rellena Payload (JSON), Metadata (JSON object), Message type, Originator type y Originator id, opcionalmente Context (optional JSON) como { "node": {…}, "flow": {…}, "global": {…} }, y selecciona Run. El resultado muestra cada salida, el registro, el contexto escrito y el tiempo de CPU. Save into the block conserva el código.
Ejemplos
Decodifica un float de 4 bytes desde un payload hexadecimal en bruto:
const data = bytes.fromHex(msg.payload.raw_hex);
msg.payload = { level_m: num.round(bytes.readFloat(data, 0, 4, { bigEndian: true }), 3) };
return msg;
Divide un mensaje con una lista de sensores en una lectura por clave de sensor:
// 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;
Enruta según una clase calculada hacia salidas con etiqueta (etiquetas ok,warn,crit):
const t = msg.payload.temperature;
if (typeof t !== 'number') return null;
return t > 8 ? 'crit' : t > 6 ? 'warn' : 'ok';
Mantén un total acumulado entre mensajes:
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;
Cuándo no usar un script
| Necesidad | Usa en su lugar |
|---|---|
| Una fórmula | Calculate |
| Renombrar, copiar o borrar claves | Change |
| Campos binarios | Bytes |
| Ramificar según un valor | Switch o If / else |
| Consumo a partir de un contador | Delta |
| Esperas | Delay, Trigger, Timer |
Consulta Bloques de transformación de datos y Límites de flujo.

