Saltar al contenido principal
Saltar al contenido principal

Payload decoder LoRaWAN: cómo integrar cualquier sensor

3 de noviembre de 202615 min
Portada de Payload decoder LoRaWAN: cómo integrar cualquier sensor

Un payload decoder LoRaWAN convierte los pocos bytes que envía un sensor en valores que la plataforma puede guardar y vigilar. Ahí fallan muchas integraciones.

En un proyecto LoRaWAN, la radio se lleva toda la atención: gateways, cobertura, spreading factors. Después llega el primer uplink y lo que aparece en la consola es `AQDrOgzk`. Eso no se puede poner en un dashboard. Entre esa cadena y «23,5 °C, 58 % de humedad, batería a 3,3 V» hay un trozo pequeño de código, y de ese código depende que añadir un modelo de sensor nuevo lleve una tarde o dos semanas.

Esta guía está pensada para integradores que tienen que conectar sensores de varios fabricantes a una misma plataforma. Explica qué hace el decoder, cómo se lee la especificación de un payload, dónde conviene que se ejecute, cómo escribirlo y probarlo, dónde encajan los downlinks y cómo mantener los decoders bajo control cuando crece el parque. Da por sabido lo básico de cómo funciona LoRaWAN.

Qué hace un payload decoder LoRaWAN

Los sensores LoRaWAN envían payloads binarios porque cada byte cuesta batería. En Europa, la velocidad de datos más lenta admite 51 bytes de carga útil de aplicación, y la más rápida, 242. Un mensaje JSON como `{"temperature":23.5,"humidity":58,"battery":3300}` ocupa 48 bytes. Los mismos tres valores caben en seis bytes en binario, y con spreading factor 12 la versión JSON pasaría casi el doble de tiempo en el aire. Esa diferencia sale directamente de la pila, como explica nuestra guía sobre la batería en sensores LoRaWAN.

Así que el equipo empaqueta sus lecturas en los menos bytes posibles, y cada fabricante las empaqueta a su manera. No hay un formato común. Dos sensores de temperatura de dos marcas envían bytes distintos para la misma lectura.

El decoder es la función que deshace ese empaquetado. Recibe tres cosas:

  • Los bytes de la carga útil de aplicación, ya descifrados por el servidor de red.
  • El puerto (`fPort`), un número del 1 al 223 que el equipo usa para indicar qué tipo de mensaje es.
  • Algo de contexto, como el identificador del equipo y la hora a la que el gateway recibió el mensaje.

Devuelve valores con nombre y en unidades de ingeniería: `temperature: 23.5`, `humidity: 58`, `battery_mv: 3300`. Unos lo llaman decoder y otros codec, parser o payload formatter. Todos hablan de la misma función.

El sentido contrario tiene su propia función, el encoder, que convierte una orden como «envía cada 30 minutos» en los bytes que espera el equipo. Una integración completa necesita las dos, aunque casi todos los proyectos empiezan por el decoder y añaden el encoder más adelante.

Leer un payload: bytes, puertos y escalas

Antes de escribir código hace falta la especificación del payload que publica el fabricante. Suele ser una tabla en el manual de usuario o un PDF aparte. Si el proveedor no puede dártela, tómalo como un aviso sobre el soporte que vas a recibir después.

Pongamos un sensor sencillo de temperatura y humedad que envía seis bytes por el puerto 2. Un uplink real, en hexadecimal:

01 00 EB 3A 0C E4

Su especificación dice esto:

PosiciónBytesCampoTipoEscalaEn este mensaje
01Tipo de mensajeSin signoNinguna01 = informe periódico
12TemperaturaCon signo, big-endian0,1 °C00 EB = 235 = 23,5 °C
31HumedadSin signo1 %3A = 58 %
42BateríaSin signo, big-endian1 mV0C E4 = 3.300 mV

De cuatro detalles de esa tabla sale la mayoría de los errores de decodificación.

El orden de los bytes. Un valor de dos bytes puede llegar con el byte alto primero (big-endian) o con el bajo primero (little-endian). `00 EB` leído al revés es 60.160, no 235. Las especificaciones no siempre dicen cuál usan, así que compruébalo con una lectura que conozcas.

El signo. La temperatura baja de cero. Una lectura de -5,0 °C en este formato es `FF CE`. Un decoder que la trate como un número sin signo informa de 6.548,6 °C. Este error pasa todas las pruebas hechas en una oficina con calefacción y aparece la primera noche de helada.

La escala. Los equipos envían enteros. La especificación indica el factor: décimas de grado, medios puntos porcentuales, milivoltios. Si te equivocas en un factor de diez, el dashboard muestra un valor creíble que está mal.

Los campos de bits. Muchos equipos meten varios indicadores en un solo byte: manipulación, batería baja, fuga detectada. Hacen falta máscaras y desplazamientos para separarlos, y la numeración de bits del manual no siempre empieza donde esperas.

El puerto importa tanto como los bytes. Los fabricantes usan puertos distintos para tipos de mensaje distintos: los datos periódicos por uno, las alarmas por otro, las respuestas de configuración por un tercero. Un decoder que no mira el puerto acabará leyendo una respuesta de configuración como si fuera una temperatura.

Dónde se ejecuta: servidor de red o plataforma

Un uplink LoRaWAN pasa por el gateway, el servidor de red y la plataforma de aplicación. El decoder puede ejecutarse en cualquiera de los dos últimos, y la elección pesa en cuanto llevas más de un proyecto.

Decoder en el servidor de redDecoder en la plataforma
Qué recibe la plataformaValores decodificados, normalmente en JSONLos bytes y el puerto
Decoders del fabricanteSuelen estar en un catálogo de dispositivosLos escribes o los adaptas
Parque repartido en dos servidores de redDos copias que mantenerUna copia
Cambio de servidor de redHay que mover los decodersNo cambia nada
Volver a decodificar datos antiguos tras un arregloSolo si también se reenviaron los bytesPosible si la plataforma guarda el payload original

En el servidor de red. The Things Stack los llama payload formatters: funciones JavaScript asociadas a una aplicación o a un equipo concreto. ChirpStack tiene un codec equivalente en el perfil de dispositivo. La ventaja es el catálogo. El repositorio de dispositivos de la comunidad reúne decoders publicados por los propios fabricantes, y para un equipo que esté en la lista puede que no tengas que escribir nada.

En la plataforma. El servidor de red reenvía el payload tal cual y la plataforma lo decodifica. Así todos los decoders quedan en un solo sitio, junto al modelo de dispositivo, las variables y las reglas de alarma que dependen de ellos. Es la mejor opción cuando tus equipos están repartidos entre más de un servidor de red, o cuando quieres poder cambiar de proveedor de red sin reescribir integraciones.

Hay además un estándar que abarata la elección. La LoRa Alliance publicó la API de codec de payload (TS013), que fija los nombres de las funciones y la forma de la entrada y la salida: `decodeUplink`, `encodeDownlink` y `decodeDownlink`. Un decoder escrito contra esa interfaz se mueve entre servidores de red compatibles con pocos cambios o ninguno.

Otro enfoque es un formato que se describe a sí mismo. Cayenne LPP antepone a cada valor un canal y un código de tipo, de modo que un único decoder genérico sirve para cualquier equipo que lo use. Cuesta dos bytes más por valor, y por eso los equipos a pilas con payloads ajustados rara vez lo usan.

Para ver el papel de cada pieza del recorrido, mira nuestra guía del servidor de red LoRaWAN.

Escribir un payload decoder LoRaWAN paso a paso

Este es un decoder para el sensor de seis bytes de antes, escrito contra la interfaz TS013 que usan tanto The Things Stack como ChirpStack.

function decodeUplink(input) {
var bytes = input.bytes;

if (input.fPort !== 2) {
return { errors: ["Unexpected port: " + input.fPort] };
}
if (bytes.length !== 6) {
return { errors: ["Expected 6 bytes, got " + bytes.length] };
}
if (bytes[0] !== 0x01) {
return { errors: ["Unknown message type: " + bytes[0]] };
}

var data = {
humidity: bytes[3],
battery_mv: (bytes[4] << 8) | bytes[5]
};
var warnings = [];

// Temperature: signed 16-bit, big-endian, tenths of a degree
var raw = (bytes[1] << 8) | bytes[2];
if (raw === 0x7FFF) {
warnings.push("Temperature probe fault");
} else {
if (raw & 0x8000) {
raw -= 0x10000;
}
data.temperature = raw / 10;
}

return { data: data, warnings: warnings };
}

Es corto, y el orden de los pasos es el mismo para cualquier equipo.

  1. Comprueba primero el puerto. Si el mensaje no es del tipo que trata esta rama, dilo y para.
  2. Comprueba la longitud. Un payload más corto o más largo de lo previsto indica otro firmware u otro mensaje. Si lo decodificas de todos modos, salen valores que parecen reales.
  3. Decodifica cada campo con su tipo. Orden de bytes, signo y escala, tal como dice la especificación.
  4. Trata los valores centinela. Muchos sensores envían un número reservado, como `7F FF`, cuando una sonda está desconectada. Sin esa comprobación, la plataforma guarda 3.276,7 °C y dispara una alarma de temperatura alta.
  5. Devuelve los errores como errores. Un decoder que devuelve cero o un objeto vacío cuando no puede decodificar esconde el problema. Un error explícito se puede contar y puede generar un aviso.

Pon a los campos de salida los mismos nombres en todos los modelos de dispositivo. Si un decoder devuelve `temperature` y otro `temp_c`, todos los dashboards y las reglas que vienen después tienen que conocer la diferencia. Una convención de nombres breve, acordada antes de que llegue el segundo modelo, ahorra ese trabajo.

Pruebas: los errores que llegan a producción

Un decoder que funciona con el sensor que tienes en la mesa se ha probado con un solo tipo de mensaje: temperatura ambiente, batería llena, buena señal, firmware actual. Los fallos vienen de todo lo demás.

Prepara para cada modelo un conjunto pequeño de vectores de prueba y guárdalo junto al decoder. Cada vector es un puerto, un payload en hexadecimal y la salida esperada.

CasoPayloadResultado esperado
Lectura normal01 00 EB 3A 0C E423,5 °C, 58 %, 3.300 mV
Bajo cero01 FF CE 50 0C 1C-5,0 °C, 80 %, 3.100 mV
Sonda averiada01 7F FF 00 0C E4Sin temperatura y un aviso
Longitud incorrecta01 00 EB 3AError
Puerto desconocidoCualquier payload por el puerto 85Error

Aparte del signo y de los valores centinela, estos son los casos que más se escapan.

  • Cambios de firmware. Una versión nueva añade un campo o cambia una escala. Si el payload lleva un byte de versión o cambia la longitud, el decoder puede bifurcar por ahí. Si no, necesitas saber qué equipos llevan qué firmware, y esa es una razón más para tener un inventario dentro de la gestión de dispositivos IoT.
  • Mensajes almacenados. Algunos equipos guardan lecturas mientras no tienen cobertura y las envían después con su propia marca de tiempo. Un decoder que no mira la hora que viene en el payload fecha lecturas antiguas con la hora de llegada, y la gráfica muestra un pico que nunca existió.
  • Contadores que dan la vuelta. Los contadores de pulsos de los medidores de agua o de energía tienen 16 o 32 bits y vuelven a cero cuando se desbordan. El decoder pasa el valor, y algo más adelante tiene que tratar esa vuelta.
  • Mensajes de join y de estado. Muchos equipos envían una trama de estado después de unirse a la red, por otro puerto, con la versión de firmware y la configuración. Si nadie la trata, es el primer error de decodificación de cada equipo.

Prueba con payloads capturados en campo. Una semana de uplinks reales de un piloto trae casos que ninguna especificación menciona.

Downlinks: la parte del encoder

Antes o después alguien pide cambiar el intervalo de envío de 400 sensores sin ir a verlos. Eso es un downlink, y necesita la función inversa.

El encoder recibe una orden en forma legible y devuelve los bytes y el puerto. Para el sensor de antes, el manual podría decir que el intervalo de envío se fija mandando `02` seguido del intervalo en minutos en dos bytes, por el puerto 3:

function encodeDownlink(input) {
var minutes = input.data.report_interval_min;

if (minutes < 5 || minutes > 1440) {
return { errors: ["Interval out of range: " + minutes] };
}

return {
fPort: 3,
bytes: [0x02, (minutes >> 8) & 0xFF, minutes & 0xFF]
};
}

Conviene saber tres cosas antes de prometerle a un cliente la configuración remota.

Los equipos de clase A solo escuchan después de transmitir. Un sensor a pilas abre dos ventanas de recepción cortas después de cada uplink y duerme el resto del tiempo. Un downlink enviado ahora espera en el servidor de red hasta el siguiente uplink, que puede tardar una hora.

Valida el rango en el encoder. Un intervalo de un minuto enviado por error a todo un parque vacía baterías y puede superar el límite de ciclo de trabajo. El encoder es el sitio adecuado para rechazarlo.

Confirma que el cambio se aplicó. Casi todos los equipos contestan a una orden de configuración con una respuesta por un puerto concreto, o incluyen el intervalo vigente en su mensaje de estado. Decodifica esa respuesta y muéstrala. Sin ella, solo sabes que la orden se envió.

Decoders a escala: versiones, modelos y parques

Con tres modelos de dispositivo, los decoders son un detalle. Con treinta, repartidos entre varios clientes, necesitan el mismo cuidado que cualquier otro código.

Un decoder por modelo de dispositivo. Asocia el decoder al modelo, no a cada equipo. Cuando se corrige un error, queda corregido para todos los equipos de ese modelo a la vez.

Decoders en control de versiones. Con sus vectores de prueba. Un decoder editado directamente en una consola web, sin historial, es la forma de que una integración que funcionaba deje de hacerlo sin que nadie sepa qué cambió.

Guarda el payload original. Si la plataforma conserva los bytes y el puerto junto a los valores decodificados, un error que se descubre tres meses después se corrige volviendo a decodificar. Si solo se guardaron los valores, las lecturas erróneas se quedan como están.

Vigila la tasa de errores. Cuenta los errores de decodificación por modelo. Una subida brusca después de una campaña de firmware te dice que el formato del payload cambió antes de que el cliente eche en falta datos.

En Cloud Studio IoT, el decoder pertenece al modelo de dispositivo. Muchos equipos tienen soporte nativo y no necesitan código. Para cualquier otro, el modelo lleva un script JavaScript con dos funciones: `parseUplink`, que la plataforma ejecuta con cada payload que recibe por LoRaWAN, MQTT o HTTP, y `buildDownlink`, que convierte una orden de la plataforma en el payload que espera el equipo. El script puede leer el payload como bytes, como texto o como JSON, y tiene disponible el puerto LoRaWAN. Si los datos ya llegaron decodificados desde The Things Stack o ThingPark X, el script puede leer esos valores directamente en lugar de decodificar otra vez. Cada ejecución es atómica: si el script falla a mitad, no se actualiza ningún valor. Los detalles están en la documentación.

Como Cloud Studio IoT recibe los datos LoRaWAN a través de servidores de red externos, y puede recibir de varios a la vez, un integrador con equipos en dos redes mantiene un solo script por modelo. Mira nuestras soluciones LoRaWAN para ver las integraciones disponibles.

Conclusión

Un payload decoder LoRaWAN son unas pocas decenas de líneas de código, y por él pasan todos los valores que ve tu cliente. Lo esencial:

  • Los sensores envían binario porque los bytes cuestan batería. Cada fabricante usa su formato, y el decoder lo traduce.
  • El orden de los bytes, el signo, la escala y los campos de bits causan la mayoría de los errores. El puerto indica qué tipo de mensaje estás leyendo.
  • El decoder puede ejecutarse en el servidor de red o en la plataforma. Tenerlo en la plataforma deja una sola copia cuando el parque está repartido entre varios servidores de red.
  • Comprueba el puerto y la longitud antes de decodificar, trata los valores centinela y devuelve errores explícitos.
  • Ten vectores de prueba con valores negativos, averías y longitudes incorrectas, y añade payloads capturados en campo.
  • Asocia los decoders a los modelos de dispositivo, tenlos en control de versiones y guarda el payload original para poder decodificar de nuevo los datos antiguos.

Si estás eligiendo sensores para un proyecto, nuestro repaso de los tipos de sensores IoT es un buen punto de partida, y la guía sobre la integración por API cubre lo que pasa con los datos una vez decodificados. Si quieres revisar cómo encajaría un equipo concreto, habla con el equipo.

Preguntas frecuentes

¿Qué es un payload decoder LoRaWAN?

Es la función que convierte los bytes que envía un sensor en valores con nombre y unidades de ingeniería, como temperatura, humedad o tensión de batería. Recibe el payload, el puerto (fPort) y algo de contexto. También se le llama codec, parser o payload formatter.

¿Por qué los sensores LoRaWAN envían binario y no JSON?

Porque cada byte cuesta batería. Tres valores que en JSON ocupan 48 bytes caben en seis bytes de binario, y en spreading factor 12 la versión JSON pasaría casi el doble de tiempo en el aire. En Europa, la velocidad más lenta solo admite 51 bytes de payload de aplicación.

¿El decoder va en el servidor de red o en la plataforma?

Las dos opciones funcionan. En el servidor de red muchas veces puedes reutilizar los decoders que publican los fabricantes en el catálogo de dispositivos. En la plataforma mantienes una sola copia cuando tus equipos están repartidos en varios servidores de red, y puedes cambiar de proveedor de red sin reescribir integraciones.

¿Qué causa la mayoría de los errores al decodificar un payload?

Cuatro detalles de la especificación: el orden de bytes, el signo, la escala y los campos de bits. Una temperatura negativa leída como entero sin signo marca miles de grados, y un factor de diez olvidado da un valor creíble pero falso. La otra causa habitual es ignorar el puerto, porque una respuesta de configuración acaba leída como una medida.

¿Qué es la API de payload codec de LoRaWAN (TS013)?

Es una especificación de la LoRa Alliance que define los nombres de las funciones y la forma de la entrada y la salida: decodeUplink, encodeDownlink y decodeDownlink. Un decoder escrito con esa interfaz se mueve entre servidores de red compatibles con pocos cambios o ninguno.

¿Cómo se prueba un payload decoder?

Guarda con cada modelo de dispositivo un conjunto de vectores de prueba: un puerto, un payload en hexadecimal y la salida esperada. Incluye una lectura normal, un valor bajo cero, un fallo de sonda, una longitud incorrecta y un puerto desconocido, y añade payloads capturados en campo durante el piloto.

Artículos Relacionados

Da el Siguiente Paso

¿Listo para Transformar tu Negocio?

Contáctanos para descubrir cómo Cloud Studio IoT puede ayudarte a alcanzar tus objetivos.