Novedad: el cortafuegos de IA supervisa cada módulo y explica cada incidente con palabras sencillas. Vea cómo funciona

Scripts de cálculo

Reestructura los datos de una tarjeta con una pequeña función JavaScript en sandbox: el contrato, lo que puede y no puede hacer, los límites, el tratamiento de errores y ejemplos prácticos.

Un compute script (mostrado como Transform en la configuración de la tarjeta) es una pequeña función JavaScript que deriva lo que dibuja una tarjeta a partir de los datos que ha cargado. Úsalo cuando ninguna fuente da exactamente la forma que necesitas: convertir unidades, emparejar dos series en una ruta, contar filas o elegir el peor estado. Un script solo calcula. No puede establecer un parámetro, ejecutar un comando, abrir una página ni acceder a la red.

Añadir un script

  1. Personaliza el tablero y abre la configuración de la tarjeta.
  2. En la pestaña Datos, abre Avanzado: calcular los valores con un script.
  3. Marca Ejecutar este script y escribe el Script.
  4. Selecciona Ejecutar ahora para ejecutar tu borrador con los datos actuales de la tarjeta. El Resultado muestra lo que se ha devuelto por cada slot, por ejemplo «series: table, 12 row(s)» y «ran in 3 ms».
  5. Define el Tiempo máximo (ms) y Cuando una ejecución falla.
  6. Selecciona Guardar.

Eliminar el script lo borra. El script se copia con la tarjeta, viaja en los archivos del tablero y permanece en la tarjeta cuando la guardas como widget.

El contrato

El script es un módulo ES cuya exportación por defecto es una función síncrona:

export default function transform({ slots, params, window, now }) {
  // slots:  the bound data by slot key, as the source returned it (shape table | scalar | series | record)
  // params: the effective board parameters of the card's page (read-only)
  // window: { from, to, interval? } (ms since the epoch) when the card's data ran with a window
  // now:    ms since the epoch, the host's clock (a script never reads Date)
  return { slots: { /* the slots you replace */ } };
}

Devuelve { slots }. Cada slot devuelto sustituye al cargado; los slots que no devuelvas se mantienen como se cargaron. Un resultado vacío dibuja los datos tal como se cargaron.

FormaForma
Escalar{ shape: 'scalar', value: 21.5, meta: { unit: '°C', decimals: 1 } }
Serie{ shape: 'series', series: [{ name: 'temperature', points: [{ t: '2026-11-09T10:00:00Z', v: 21.5 }] }] }
Tabla{ shape: 'table', columns: [{ key: 'id' }, { key: 'value', type: 'number' }], rows: [{ id: 'p1', value: 3 }] }
Registro{ shape: 'record', record: { level: 2.4, flow: 18 } }

Una tarjeta de diagrama de proceso o de modelo 3D también puede devolver scene: elementos, sustituciones por objeto, conexiones y zonas adicionales, la vista y los problemas. Solo cambia el dibujo.

Dónde se ejecuta

El script se ejecuta en tu navegador, en un marco oculto sin acceso a Hermetry, a la red ni a tu sesión, dentro de su propio worker. Se vuelve a ejecutar cada vez que cambian los datos de la tarjeta (incluida una actualización en vivo) o un parámetro. Solo hay una ejecución en curso por tarjeta; gana la entrada más reciente, con un máximo de 20 ejecuciones por segundo. Una tarjeta que no se muestra no se ejecuta. Las pantallas de visualización ejecutan scripts de la misma forma.

Límites

LímiteValor
Longitud del script65,536 caracteres
Tiempo máximoDe 10 a 500 ms por ejecución, por defecto 50. Si se supera, la ejecución se detiene.
Slots devueltos16
Filas por tabla5,000
Columnas64
Un valor de texto10 KiB
Resultado completo2 MiB
Elementos en una escena500 en un diagrama de proceso, 2,000 en un modelo 3D

Cuando una ejecución falla

Cuando una ejecución fallaLa tarjeta
Mantener el resultado anteriorMantiene la última salida correcta y muestra una insignia Transform failed
Mostrar la tarjeta vacíaMuestra el error en lugar de los datos

Mensajes: «The script ran past its time budget: …», «The script could not be loaded: …», «Transform failed: …».

Ejemplos

De Celsius a Fahrenheit en una tarjeta de valor (slot value):

export default function transform({ slots }) {
  const c = slots.value && typeof slots.value.value === 'number' ? slots.value.value : null;
  if (c === null) return {};
  return { slots: { value: { shape: 'scalar', value: c * 9 / 5 + 32, meta: { unit: '°F', decimals: 1 } } } };
}

Contar las alarmas abiertas de los dispositivos de un parámetro (una tarjeta de valor cuyo slot value está vinculado a Alarms (live), una tabla):

export default function transform({ slots }) {
  const rows = slots.value && Array.isArray(slots.value.rows) ? slots.value.rows : [];
  return { slots: { value: { shape: 'scalar', value: rows.length, meta: { decimals: 0 } } } };
}

Una ruta a partir de series de latitud y longitud (un mapa cuyo slot routes está vinculado a Device readings over time con las claves lat,lng):

export default function transform({ slots }) {
  const series = slots.routes && Array.isArray(slots.routes.series) ? slots.routes.series : [];
  const named = (k) => series.find((s) => s && s.name === k) || { points: [] };
  const lng = new Map(named('lng').points.map((p) => [p.t, p.v]));
  const track = named('lat').points
    .filter((p) => lng.has(p.t))
    .map((p) => [p.v, lng.get(p.t), Date.parse(p.t)])
    .sort((a, b) => a[2] - b[2]);
  return { slots: { routes: { shape: 'table',
    columns: [{ key: 'name' }, { key: 'positions' }],
    rows: track.length >= 2 ? [{ id: 'route', name: 'Route', positions: track.slice(-256) }] : [] } } };
}

Una lista dentro de una celda contiene como máximo 256 elementos, así que limita una ruta a 256 puntos. Consulta Tarjetas de mapa.

Buenas prácticas

  • Devuelve solo los slots que cambies.
  • Protégete contra datos ausentes: un slot puede estar vacío mientras el dispositivo no envía nada.
  • Mantén los scripts pequeños y rápidos; un bucle largo sobre un año de lecturas brutas superará el tiempo máximo. Prefiere una fuente con agregado.
  • Usa now, nunca Date.now(), para cualquier cosa basada en el tiempo.