Abrir versión de texto

Contenido del artículo
- 1. Los sistemas de alarma rara vez fallan por quedarse en silencio
- 2. Tres presupuestos de tiempo que hay que calcular primero
- 3. Tres componentes, y los tres son obligatorios
- 4. El entorno de ejecución: cuerpo de función desnudo en un sandbox vm2
- 5. Cuatro campos de retorno, uno de los cuales es un filtro de ruido libre
- 6. Un script que puedes copiar
- 7. Cuatro niveles de gravedad y una matriz de enrutamiento
- 8. Seis formas de reducir el ruido
- 9. Grupos de notificación: qué admiten realmente
- 10. Tres recetas que puede aplicar directamente
- 11. Lista de verificación previa al lanzamiento
- 12. Ocho errores vistos repetidamente
- Cierre
1. Los sistemas de alarma rara vez fallan por quedarse en silencio
La mayoría de los proyectos de IoT le piden una sola cosa a las alarmas: «que hagan ruido cuando algo se rompe». Pero lo que realmente mata a un sistema de alarmas no es el silencio, sino las alertas que nadie lee.
Datos públicos sobre la magnitud del problema:
| Métrica | Valor | Fuente |
|---|---|---|
| Volumen diario de alertas en un centro de operaciones de seguridad | ~2,992/día, con alrededor de 63% nunca atendidas | Vectra AI 2026 |
| Misma imagen, muestra distinta | ~2,047/día, de las cuales 300 (15%) quedan sin revisar por falta de recursos | Binalyze, 2026 State of the SOC (encuesta de Sapio a 400 CISOs) |
| Consecuencia de la sobrecarga | 91% de los CISOs informan de sobrecarga de información; 77% dicen que les hizo pasar por alto una advertencia o una vulnerabilidad | Misma |
| Tasa de falsas alarmas industriales | 40%–90% de las alarmas de sensores resultan ser falsas (deriva, ruido ambiental, degradación de la calibración) | Rango consistente en los estudios de mantenimiento industrial |
| Coste de la repetición | Cada alerta repetida del mismo tipo reduce las probabilidades de que un operador actúe en aproximadamente 30% | Investigación sobre gestión de alarmas industriales |
Una cifra que merece convertirse: en una planta que monitorea 180 activos, una tasa de falsos positivos del 35% consume alrededor de 1,200 horas de técnico al año persiguiendo nada — cerca de US$42,000 anuales.
(Las dos primeras filas provienen de operaciones de seguridad, no de IoT. Sin embargo, el mecanismo es idéntico: cuanto más alto es el nivel de ruido, más fácilmente desaparece en él la única alerta que importa.)
Así que este artículo no trata de generar más alertas. Trata de tres propiedades:
- Llega a tiempo — la alarma se dispara dentro de un ciclo de reporte, garantizado y documentado;
- No genera spam — un evento produce una alarma, y esta se despeja sola cuando la condición desaparece;
- Llega a la persona correcta — lo urgente va a un teléfono, lo rutinario va a una lista, y ambos nunca se mezclan.
2. Tres presupuestos de tiempo que hay que calcular primero
En LoRaWAN, el primer paso de diseño no es escribir un script. Es aceptar un hecho físico: un dispositivo final alimentado por batería no se despertará antes solo porque algo haya fallado. Eso produce tres líneas de tiempo:
| Etapa | Determinada por | Magnitud típica | Qué puede hacer |
|---|---|---|---|
| Latencia de detección | Periodo de enlace ascendente (intervalo de recolección + reporte por cambio de valor) | 5–60 minutos; más si el COV nunca se activa | Acorte el intervalo de recolección o ajuste el umbral de COV |
| Latencia de enlace descendente | Los dispositivos Clase A solo abren ventanas de recepción después de su propio enlace ascendente (RX1 ≈ 1 s, RX2 ≈ 2 s según los valores predeterminados de LoRaWAN 1.0.4); si las pierde, espera al siguiente enlace ascendente | 1–2 s en el mejor caso, un periodo completo de enlace ascendente en el peor | Use Clase C para bucles críticos; de lo contrario, incluya la latencia en el SLA |
| Detección de desconexión | La plataforma marca un dispositivo como desconectado tras «última hora de actividad + 2 × periodo de latido» | Depende del latido configurado | Configure el latido en 2–3× el periodo de enlace ascendente |
La conclusión: LoRaWAN no puede entregar alarmas de nivel de segundos, pero sí puede entregar alarmas que nunca lleguen más tarde que un ciclo de reporte. Ponga esa frase en la propuesta antes de que un cliente la descubra durante las pruebas de aceptación.
Lleva esta guía a tu proyecto
ManThink ofrece productos IoT para conectar dispositivos, desplegar redes y trabajar con datos. Consulta estos recursos de producto junto con las recomendaciones técnicas del artículo:
3. Tres componentes, y los tres son obligatorios
La generación de alarmas en ThinkLink no es «poner un umbral en el dispositivo». Son tres partes trabajando juntas:
| Parte | Responsabilidad | Dónde configurarla |
|---|---|---|
| Modelo de disparador | Ejecuta un script en cada enlace ascendente, evalúa condiciones y devuelve acciones | Gestión de modelos → Modelo de disparador → asociar al dispositivo |
| RPC ALARM integrado | Acepta action: new / clear, crea o despeja el registro de alarma, lo despacha a los grupos de notificación |
Gestión de dispositivos → detalle del dispositivo → RPC → añadir ALARM |
| Grupo de notificación | Decide quién la recibe y por qué canal | Gestión de alarmas → Grupo de notificación |
El orden es fijo: asocie el ALARM RPC primero, luego el modelo de disparador y después (opcionalmente) el grupo de notificación. Si falta cualquiera de ellos, la alarma queda muda — no existe eso de «el script existe, así que sonará».
Un dispositivo puede llevar múltiples modelos de disparador, de modo que los escenarios con múltiples condiciones no tienen que amontonarse en un solo script.
4. El entorno de ejecución: cuerpo de función desnudo en un sandbox vm2
Un detalle desconcierta a casi todos: el editor espera un cuerpo de función desnudo. La plataforma envuelve tu código en function triggerRunner() { ... } antes de llamarlo, así que no debes añadir otro function trigger_script(...) {} envoltorio. La trigger_script forma aparece en la documentación solo para ilustrar qué variables están disponibles.
El sandbox es vm2, con estos límites:
| Elemento | Valor |
|---|---|
| Tiempo de espera de ejecución | 1000 ms; superarlo omite este disparador por completo |
eval / WebAssembly |
Deshabilitado |
async / await |
No compatible; los scripts se ejecutan de forma síncrona |
require / import |
No compatible |
setTimeout / setInterval / console |
No disponible — usa el delayms campo de retorno para la ejecución diferida, y el registro del modelo de disparador para la depuración |
process / path / fs |
No disponible |
Buffer |
SafeBuffer, que expone solo alloc, from, isBuffer, byteLength, compare, concat |
Variables inyectadas que puedes usar directamente: device, thingModelId, org_params, env, plugins, Buffer, además de las seis tklHelper clases (BufferTKL, PayloadParser, MSparser, Utils, TriggerHelper, RPCHelper).
Campos de device que más importan para las alarmas:
| Campo | Significado |
|---|---|
device.telemetry_data[thingModelId] |
Última instantánea de telemetría para ese modelo de thing (el punto de entrada para las lecturas) |
device.server_attrs |
Atributos del lado de la plataforma; el lugar adecuado para umbrales, grupos de notificación, EUIs vinculados |
device.shared_attrs |
Atributos sincronizados en ambos sentidos con el dispositivo |
device.active_time |
Marca de tiempo del último uplink (ISO 8601) |
device.heart_period |
Periodo de heartbeat en segundos, usado para la detección de desconexión |
device.eui / device.name |
Identificador y nombre del dispositivo |
Ten en cuenta que device y las clases auxiliares se inyectan congeladas — las asignaciones a ellas no tienen efecto. El valor de retorno es el único canal de salida.
5. Cuatro campos de retorno, uno de los cuales es un filtro de ruido libre
Un script de disparador devuelve null (no hacer nada) o un objeto con estos campos:
| Campo | Tipo | Significado |
|---|---|---|
delayms |
Número | Retardo en milisegundos antes de ejecutar actions |
abort_previous_timer |
Booleano | Cuando true, cancela la tarea diferida pendiente anterior y la reemplaza por esta |
should_dispatch |
Booleano | Por defecto false: si los datos no han cambiado desde la última vez, se omite el despacho. Establece true para forzarlo |
actions |
Array | Llamadas RPC ejecutadas en orden |
Campos de cada actions elemento:
| Campo | Significado |
|---|---|
method |
Nombre del método RPC (alarm para alarmas) |
methodId |
Alternativa a method; tiene prioridad cuando ambos están presentes |
params._eui |
EUI del dispositivo de destino — dentro de params, no un campo de nivel superior de la acción |
should_dispatch con valor predeterminado false es el primer filtro de ruido que obtienes gratis. Datos idénticos en uplinks consecutivos no volverán a despachar acciones. Muchos equipos no lo saben y construyen su propia deduplicación encima de esto.
6. Un script que puedes copiar
Temperatura más batería, con umbrales y grupos de notificación externalizados en server_attrs de modo que cambiar un umbral nunca toque el script:
// El script de disparo es un cuerpo de función desnudo; la plataforma lo envuelve en triggerRunner() let tdata = device?.telemetry_data?.[thingModelId]; if (!tdata) return null;
const LIMIT_TEMP = device.server_attrs?.alarm_temp ?? 60; const LIMIT_BAT = device.server_attrs?.alarm_battery ?? 20; const notify = device.server_attrs?.notify ?? [];
let actions = [];
// 1) Sobrecalentamiento: mantén el título y el nivel estables para que la deduplicación funcione let hot = tdata.temperature >= LIMIT_TEMP; actions.push({ method: "alarm", params: { _eui: device.eui, name: "overheat_alarm", title: "[Overheat] " + device.name, level: "urgent", desc: "Temperature above limit, immediate action required", action: hot ? "new" : "clear", notify: notify } });
// 2) Batería baja: solo registro, no molestar (array notify vacío) let lowBat = tdata.battery <= LIMIT_BAT; actions.push({ method: "alarm", params: { _eui: device.eui, name: "low_battery_alarm", title: "[Low battery] " + device.name, level: "mid", desc: "Battery below threshold, schedule a replacement", action: lowBat ? "new" : "clear", notify: [] } });
return { delayms: 0, abort_previous_timer: true, actions };
Parámetros del RPC ALARM:
| Parámetro | Significado |
|---|---|
name |
Identificador único del evento de alarma; un nombre por tipo de alarma |
action |
new activa, clear despeja, no no hace nada |
title |
Título mostrado en la interfaz de usuario |
desc |
Texto de descripción |
level |
low / mid / high / urgent |
notify |
Array de nombres de grupos de notificación; array vacío significa registrar pero no enviar |
Coincidencia server_attrs en el dispositivo:
| Campo | Ejemplo | Propósito |
|---|---|---|
alarm_temp |
60 | Umbral de temperatura |
alarm_battery |
20 | Umbral de batería |
notify |
["ops-team"] |
Lista de grupos de notificación |
Si prefieres no construir a mano el objeto de retorno, extiende TriggerHelper y sobrescribe _alarmProcess(info). El constructor lee device.server_attrs.notify automáticamente y produce la estructura de retorno estándar (donde el campo se llama group, correspondiente a notify en el RPC ALARM). Si _alarmProcess devuelve false, o la acción es no, alarm() devuelve null.
7. Cuatro niveles de gravedad y una matriz de enrutamiento
Hay exactamente cuatro niveles: low (informativo), mid (advertencia), high (error), urgent (crítico). El nivel en sí no dispara nada — lo que importa es la combinación nivel × grupo de notificación:
| Situación | Nivel sugerido | notify | Respuesta esperada |
|---|---|---|---|
| Fuga de agua, gas, sobrecalentamiento de sala de servidores | urgent |
Grupo de guardia (webhook de WeCom) | Inmediatamente |
| Fuera de rango pero tolerable (deriva de temperatura) | high |
Correo del equipo de operaciones | Mismo turno |
| Batería baja, calidad de señal degradada | mid |
Array vacío, solo listado | Trabajo programado |
| Parámetro cambiado, discrepancia de versión de firmware | low |
Array vacío | Próxima inspección |
Acuerda esta tabla con el cliente durante el arranque. La gravedad de la alarma no es una cuestión técnica, es una cuestión de propiedad — cada nivel necesita un responsable con nombre, de lo contrario urgent termina tan ignorado como todo lo demás.
8. Seis formas de reducir el ruido
-
Deja
should_dispatchen paz. Sufalsevalor predeterminado significa que los datos sin cambios no se vuelven a enviar. Establézcalo solotruecuando realmente se requiera un envío forzado cada vez. -
Mantenga
name,title,levelydescestables. La plataforma suprime una alarma idéntica en nombre, título, descripción y nivel. Por lo tanto, no concatene la lectura en vivo endesc— 61.2 y 61.5 son dos alarmas diferentes, la deduplicación se rompe y se despierta con cuarenta entradas. Si necesita mostrar un valor, muestre una banda o una categoría ("por encima del límite superior"). -
Use por defecto
clear. Establezcaactionencleary cambie anewsolo cuando se cumpla la condición. Cada enlace ascendente actúa entonces también como verificación de recuperación, y las alarmas desaparecen por sí solas una vez que todo es normal. Haga lo contrario (envíenewsolo en caso de incumplimiento) y la alarma quedará colgada para siempre si el dispositivo se desconecta. -
Use
delaymspara verificaciones de persistencia. Para mediciones ruidosas (contactos de puerta, fugas de agua, excursiones momentáneas), no genere la alarma en el primer incumplimiento. Devuelva undelaymsconabort_previous_timer: truepara que cada nuevo enlace ascendente cancele la acción pendiente anterior — solo una excursión sostenida sobrevive el tiempo suficiente para convertirse en alarma. -
Coloque los umbrales y los grupos en
server_attrs. Cambiar un umbral entonces no requiere editar el script, ni una nueva versión, ni una reasociación. Quinientos dispositivos pueden compartir un modelo de disparador y cada uno mantener sus propios umbrales — eso es lo que hace posible esta escala. -
Exija dos señales para la escalada. Temperatura alta mientras la humedad también se mueve es un nivel de confianza distinto al de un pico de temperatura aislado. El incumplimiento de un solo parámetro se queda en
mid; dos parámetros juntos escalan ahigh. Esto elimina una parte significativa de los falsos positivos.
9. Grupos de notificación: qué admiten realmente
Los grupos de notificación se encuentran en Gestión de alarmas → Grupo de notificación. Id, nombre, método de notificación y contactos son obligatorios; las etiquetas y las notas son opcionales.
| Elemento | Comportamiento real |
|---|---|
| Métodos integrados | Correo electrónico (predeterminado) y webhook de WeCom |
| Contactos | Selección múltiple |
| Interruptor de habilitación | Desactivado por defecto — debe activarlo |
| DingTalk / Slack / Telegram | No están en el formulario integrado; requieren un RPC personalizado |
Esto merece énfasis: describir DingTalk, Slack y Telegram como canales integrados es inexacto. Son accesibles mediante un RPC personalizado, lo cual es real pero no una casilla de verificación. Descríbalo tal cual, o las pruebas de aceptación no coincidirán con la propuesta.
Un hábito práctico: almacene los nombres de los grupos como un arreglo en device.server_attrs (por ejemplo notify: ["ops-team"]) y pásalo directamente a notify. El enrutamiento por gravedad se convierte entonces en un cambio de atributo en lugar de un cambio de script — el mismo modelo de disparador en 500 dispositivos puede enrutar cada dispositivo a su propio grupo.
10. Tres recetas que puede aplicar directamente
| Escenario | Condición | Nivel | Notificar | Resuelta por |
|---|---|---|---|---|
| Fuga de agua KS52 | water_leak == 1 |
urgent |
Grupo de guardia de WeCom | Siguiente enlace ascendente con lectura normal |
| Batería baja | battery <= 20 |
mid |
Arreglo vacío (solo lista) | Tras el reemplazo de la batería |
| Dispositivo desconectado | active_time más antiguo que 2 × heart_period |
high |
Correo electrónico del equipo de operaciones | Siguiente enlace ascendente |
Una advertencia sobre la detección de desconexión: la plataforma expone tres nociones distintas de estar en línea (la base de tiempo de actividad usada en listas y estadísticas, el server_attrs.online detector, y la data.online notificación MQTT). No son intercambiables. Cuando implemente alarmas de desconexión en un script de disparador, indique explícitamente que está usando active_time y heart_period, y documéntelo.
11. Lista de verificación previa al lanzamiento
- [ ] El
ALARMRPC está asociado al dispositivo de destino (no solo al modelo de disparador) - [ ] El modelo de disparador está asociado en la pestaña Trigger del dispositivo (no solo creado)
- [ ]
_euiestá presente dentro deparams, no en el nivel superior de la acción - [ ]
namees único y estable, un nombre por tipo de alarma - [ ]
leveles uno de los cuatro valores legales — un nivel ausente significa que no hay alarma - [ ] Los umbrales y los grupos están en
server_attrs, y el script tiene valores predeterminados cuando faltan - [ ]
actionpor defecto esclear, no "enviarnewsolo al incumplirse" - [ ]
descno incorpora la lectura en vivo (de lo contrario falla la deduplicación) - [ ] El grupo de notificaciones se ha habilitado manualmente (por defecto está desactivado)
- [ ] Se han ejercitado tanto las rutas
newcomoclearen la pestaña de prueba del editor
12. Ocho errores vistos repetidamente
| Síntoma | Causa |
|---|---|
| El script nunca se ejecuta | El modelo de disparador se creó pero nunca se vinculó al dispositivo |
| El script se ejecuta, no aparece ninguna alarma | El ALARM RPC no está vinculado al dispositivo |
| Spam de alarmas | Valores en vivo concatenados en desc, omitiendo la deduplicación |
| Alarmas que nunca se despejan | Solo se envía new ; una vez que un dispositivo se desconecta, la alarma queda colgada |
| El cambio de umbral no tiene efecto | Umbral codificado de forma fija en el script mientras usted editaba server_attrs |
ReferenceError en el script |
Se usó console, setTimeout o process, ninguno de los cuales inyecta el sandbox |
| El script parece colgarse | Se usó async/await; el sandbox es síncrono |
| "Marcar todo como leído" tratado como recuperación | Ese es un estado de lectura; el despeje de alarmas y la entrega de notificaciones son dos cosas separadas |
Cierre
Un sistema de alarmas utilizable no se define por su script. Se define por tres decisiones de criterio: qué cuenta como una anomalía real, quién debe saberlo y cuándo mantenerse en silencio. ThinkLink entrega las tres a los scripts y a la configuración de atributos — lo bastante flexible como para que un modelo pueda servir a 500 dispositivos con umbrales distintos, a costa de exigir que alguien piense bien las reglas antes de la puesta en marcha.
De las seis técnicas de reducción de ruido anteriores, las dos que más a menudo se omiten son la número 2 (mantener desc estable) y la número 3 (por defecto en clear). Omita cualquiera de las dos y el sistema parecerá correcto durante la primera semana — luego nadie volverá a abrir la lista de alarmas.
Siguiente en la serie (número 23): mantener los datos dentro de la planta — desplegar ThinkLink Edge (TKE) en las instalaciones, desde la selección de hardware y Docker Compose hasta la migración bidireccional de modelos de dispositivos con la nube.
ManThink: de los dispositivos a las aplicaciones de datos
¿Planeas una nueva instalación o modernizar un sistema existente? Comparte con ManThink la región, el número de dispositivos, las interfaces de campo y las condiciones de conectividad y alimentación para conversar sobre la selección de productos y la integración.
KS52 Sensor de temperatura, humedad y fugas
KS52 — Mide temperatura y humedad relativa, con sondas de fugas opcionales. La pantalla LCD de bajo consumo permite lectura local y supervisión remota.
ThinkLink
ThinkLink conecta dispositivos IoT con aplicaciones de datos y permite la conexión de dispositivos, la gestión de datos y el desarrollo de aplicaciones.
Consulta tu proyecto con ManThink →
Confirma los modelos, las configuraciones y las condiciones de uso en la documentación oficial y según los requisitos de tu proyecto.
Artículos relacionados
Edificios y climatización · Socios globales · Consulta tu proyecto ↗
Descubre más notas técnicas y experiencias de campo.
Volver a los artículos ↗