IoT industrial

Datos de series temporales industriales: muestreo, compresión y almacenamiento

Cómo muestrear, comprimir, poner timestamp y almacenar los datos de series temporales industriales que circulan por MQTT, con código de deadband, una configuración de Telegraf y una tabla para decidir el almacenamiento.

Gráfico de datos de series temporales industriales con muestras brutas de sensor, puntos comprimidos por deadband y niveles de almacenamiento del edge al historian
Pruébalo en tu propio broker MQTTConsigue un broker MQTT privado y gestionado con el plan Free y empieza con ejemplos de código listos para usar.
Pruébalo gratis Ejemplos de código Sin tarjeta

Los datos de series temporales industriales son el flujo de mediciones con timestamp que máquinas, sensores y controladores producen cada segundo de cada turno. Gestionarlos bien implica decidir con qué frecuencia muestrear, qué descartar, cómo asignar timestamps y dónde guardarlos. Este artículo recorre cada una de esas decisiones y te ofrece código funcional para aplicar compresión deadband a los datos MQTT antes de que lleguen a un historian.

Qué diferencia a los datos de series temporales industriales

Todas las series temporales tienen la misma forma: un timestamp, un identificador y un valor. Los datos industriales añaden varias complicaciones que los datos de monitorización de IT rara vez tienen.

  • Ritmos de cambio muy distintos. El nivel de un tanque cambia lentamente a lo largo de horas; una señal de vibración cambia miles de veces por segundo. Una única política de muestreo no sirve para ambas.
  • Requisitos de retención largos. Las investigaciones de calidad, los registros regulatorios y el entrenamiento de modelos a menudo necesitan años de histórico, no semanas.
  • La calidad importa tanto como el valor. Un valor procedente de un sensor desconectado no es una medición. Los sistemas industriales acompañan cada punto de un indicador de calidad.
  • Datos de eventos y estados mezclados con datos analógicos. Estados de máquina, alarmas, IDs de lote y cambios de receta son escasos y deben combinarse con señales analógicas densas.
  • Relojes que no controlas. PLC, gateways y servidores tienen cada uno su propio reloj, y derivan.

Acertar en esto desde el principio es mucho más barato que reparar años de histórico incoherente después.

Elegir las frecuencias de muestreo

La frecuencia de muestreo debe seguir la física de la señal y la pregunta que quieres responder, no el tiempo de ciclo por defecto del PLC.

Tipo de señal Comportamiento típico Enfoque práctico
Temperaturas, niveles, presiones lentas Cambian en segundos o minutos Muestrear cada 1–10 s, comprimir con deadband
Caudales, corriente de motor, velocidades Cambian en fracciones de segundo o segundos Muestrear cada 100 ms–1 s, comprimir con deadband
Estado de máquina, alarmas, contadores Eventos discretos Publicar solo cuando cambian (informe por excepción)
Vibración, acústica, calidad de energía Cambian en milisegundos Muestrear a kHz en el edge, publicar características (RMS, pico, bandas)

Dos reglas ayudan. Primera, el principio de Nyquist: para ver una variación, muestrea al menos al doble de su velocidad y, en la práctica, varias veces más rápido. Segunda, no transmitas por MQTT formas de onda brutas de alta frecuencia de forma continua. Calcula características en el edge y publica esas características; envía instantáneas en bruto solo bajo demanda o ante eventos.

Para los datos discretos, el informe por excepción es el patrón natural. El artículo sobre report by exception explica cómo reduce el tráfico sin perder información.

Compresión: conservar la señal y descartar el ruido

En los historians industriales, la compresión suele significar un filtrado con pérdida en la ingesta, no archivos zip. El objetivo es almacenar menos puntos sin dejar de poder reconstruir la señal dentro de una tolerancia conocida.

Filtrado por deadband (excepción)

El método más sencillo: guardar un punto nuevo solo cuando el valor difiere del último almacenado en más de un umbral. Un deadband de 0,2 degC en una temperatura significa que las fluctuaciones inferiores a 0,2 degC no se guardan. La mayoría de las implementaciones también guardan un punto tras un tiempo máximo aunque nada haya cambiado (un heartbeat), para que los consumidores distingan una señal estable de una muerta.

Compresión swinging door

El swinging door trending, utilizado en muchos historians comerciales, conserva un punto solo cuando una línea recta desde el último punto almacenado ya no puede representar los valores intermedios dentro de la tolerancia. Conserva las pendientes mucho mejor que un deadband simple, de modo que las rampas se guardan con pocos puntos en lugar de muchos.

Elegir las tolerancias

Fija la tolerancia en relación con la precisión del sensor, no con un porcentaje arbitrario. Filtrar por debajo del nivel de ruido del sensor almacena ruido; filtrar muy por encima pierde cambios reales del proceso. Documenta la tolerancia por tipo de tag en tu modelo de datos IIoT para que se revise como cualquier otro atributo del modelo.

Compresión deadband de datos MQTT en Python

Este suscriptor lee telemetría JSON desde MQTT, aplica un deadband con heartbeat y escribe los puntos que sobreviven en InfluxDB line protocol por la salida estándar, que puedes redirigir a un archivo o canalizar hacia un escritor. Usa el servidor MQTT público gratuito con un simulador de demo integrado; reserva ese servidor para pruebas y prototipos, nunca para datos de producción.

import json
import math
import random
import threading
import time
import uuid

import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:8]}/plant1/line1"
DEADBAND = {"temperature": 0.2, "pressure": 0.05}
HEARTBEAT_S = 60

last_stored = {}  # topic -> (valor, ts_segundos)


def keep(topic, metric, value, ts):
    prev = last_stored.get(topic)
    if prev is None:
        return True
    band = DEADBAND.get(metric, 0.0)
    return abs(value - prev[0]) > band or ts - prev[1] >= HEARTBEAT_S


def on_connect(client, userdata, flags, reason_code, properties):
    client.subscribe(f"{PREFIX}/+/+", qos=1)


def on_message(client, userdata, msg):
    asset, metric = msg.topic.split("/")[-2:]
    p = json.loads(msg.payload)
    ts = p["ts"] / 1000
    if keep(msg.topic, metric, p["value"], ts):
        last_stored[msg.topic] = (p["value"], ts)
        print(f'{metric},asset={asset},quality={p["quality"]} value={p["value"]} {int(p["ts"] * 1e6)}')


def simulate(pub):
    t0 = time.time()
    while True:
        t = time.time() - t0
        temp = 60 + 5 * math.sin(t / 120) + random.gauss(0, 0.05)
        pres = 2.5 + random.gauss(0, 0.01)
        ts = int(time.time() * 1000)
        for metric, val in [("temperature", temp), ("pressure", pres)]:
            body = {"value": round(val, 3), "ts": ts, "quality": "GOOD"}
            pub.publish(f"{PREFIX}/pump1/{metric}", json.dumps(body), qos=0)
        time.sleep(1)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="tsdb-" + uuid.uuid4().hex[:8])
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, 1883, keepalive=60)
threading.Thread(target=simulate, args=(client,), daemon=True).start()
client.loop_forever()

Ejecútalo unos minutos y cuenta las líneas: la presión, que solo muestra ruido por debajo de su deadband, genera aproximadamente un punto por minuto (el heartbeat), mientras que la temperatura genera puntos a medida que se mueve la onda senoidal. Ese es exactamente el comportamiento que quieres de un historian: denso donde el proceso se mueve y escaso donde no.

Timestamps y orden

Asigna siempre el timestamp en el origen, lo más cerca posible de la medición, en UTC y con milisegundos. La hora de llegada al broker no es la hora de medición, sobre todo cuando un gateway edge almacena datos en búfer durante un corte de red y los reenvía después. El patrón store and forward depende de los timestamps de origen para colocar los datos tardíos en su sitio.

Sincroniza los relojes con NTP o PTP en los gateways y, siempre que sea posible, en los controladores. Cuenta con llegadas fuera de orden y asegúrate de que tu almacenamiento acepta escrituras en el pasado. Algunas bases de datos de series temporales gestionan bien las escrituras tardías; otras las penalizan.

Opciones de almacenamiento para datos de series temporales industriales

Opción Puntos fuertes Cuidado con
Historian de proceso comercial Compresión, calidad, modelos de activos y retención larga integrados Licencias, acceso propietario
Base de datos de series temporales (InfluxDB, TimescaleDB, QuestDB) Interfaces abiertas, consultas SQL o Flux, buenas tasas de escritura Tú diseñas la compresión, la retención y el submuestreo
Data lake (Parquet sobre almacenamiento de objetos) Almacenamiento a largo plazo barato, ideal para entrenar ML No sirve para consultas en tiempo real
Combinación por niveles Datos calientes en la TSDB, datos fríos en el lake Dos sistemas que operar

Muchas plantas combinan un historian o una TSDB para los datos recientes con un lake para la analítica a largo plazo. El artículo sobre el historian MQTT explica cómo construir la parte del historian directamente a partir de los topics MQTT.

Llevar los datos del broker al almacenamiento

Un broker es un enrutador, no una base de datos: los mensajes lo atraviesan y los retained messages solo conservan el último valor por topic. Para guardar el histórico ejecutas un escritor que se suscribe e inserta. Telegraf es una elección habitual:

[[inputs.mqtt_consumer]]
  servers = ["ssl://broker.connectmq.com:8883"]
  topics = ["connectmq/plant1/#"]
  client_id = "YOUR_CLIENT_ID"
  username = "YOUR_USERNAME"
  password = "YOUR_PASSWORD"
  qos = 1
  data_format = "json"
  json_time_key = "ts"
  json_time_format = "unix_ms"
  tag_keys = ["quality"]

  [[inputs.mqtt_consumer.topic_parsing]]
    topic = "connectmq/+/+/+/+"
    tags = "_/site/line/asset/_"
    measurement = "_/_/_/_/measurement"

[[outputs.influxdb_v2]]
  urls = ["http://localhost:8086"]
  token = "YOUR_INFLUX_TOKEN"
  organization = "plant"
  bucket = "telemetry"

Con ConnectMQ como broker MQTT gestionado, Telegraf es simplemente otro cliente autenticado sobre TLS en el puerto 8883. Usa QoS 1 en la suscripción del escritor para que una desconexión breve no pierda datos en silencio, y mantén persistente la sesión del escritor si quieres que los mensajes se encolen mientras se reinicia.

Lista de comprobación para datos de series temporales industriales

  1. Clasifica cada señal: analógica lenta, analógica rápida, discreta o de alta frecuencia.
  2. Fija el muestreo y el deadband por clase, según la precisión del sensor.
  3. Añade un heartbeat para distinguir las señales estables de las muertas.
  4. Asigna el timestamp en el origen, en UTC y con milisegundos.
  5. Publica la calidad con cada valor.
  6. Calcula características en el edge para las señales de kHz.
  7. Elige el almacenamiento caliente y frío y define la retención y el submuestreo.
  8. Prueba las escrituras tardías y fuera de orden antes de la puesta en marcha.

Para la arquitectura que rodea todo esto, consulta la guía de IoT industrial con MQTT.

Empieza con ConnectMQ

Crea un broker Serverless gratuito en app.connectmq.com, sin tarjeta de crédito, y conecta después tu gateway y un escritor de Telegraf o Python con las credenciales generadas. El explorador de topics en vivo de ConnectMQ te ayuda a comprobar las tasas de publicación y los payloads antes de fijar una política de muestreo y compresión.

Preguntas frecuentes

¿Qué son los datos de series temporales industriales?

Son datos de mediciones y eventos con timestamp producidos por equipos industriales, como temperaturas, presiones, velocidades, estados y contadores. Normalmente se almacenan con un indicador de calidad y se conservan durante largos periodos para operaciones, calidad y analítica.

¿Cuál es un buen valor de deadband?

Empieza cerca de la precisión o del nivel de ruido del sensor para esa medición y comprueba después que los cambios importantes del proceso siguen viéndose en los datos almacenados. Documenta el valor por tipo de tag y revísalo cuando cambien los sensores.

¿Puede un broker MQTT almacenar histórico de series temporales?

No. Un broker enruta mensajes y conserva como mucho el último valor retenido por topic. Guarda el histórico con un suscriptor como Telegraf, un conector de historian o tu propio escritor.

¿Debo transmitir por MQTT los datos brutos de vibración?

Normalmente no de forma continua. Calcula en el edge características como RMS, pico y energía por bandas y publícalas, y envía instantáneas de la forma de onda en bruto solo bajo petición o cuando un evento las desencadene.

Artículos relacionados

Todos los artículos →

Tu broker MQTT privado, a unos pocos clics

Crea una cuenta, obtén las credenciales de tu broker y conecta tu primer dispositivo, sin servidores que instalar, parchear ni escalar.