pasar de JSON a MsgPack de forma compatible con Paho MQTT (JavaScript)

picockpit.com hace un uso intensivo de MQTT. Para la próxima versión 2.0 he decidido cambiarla por MsgPack.

¿Por qué MsgPack?

MsgPack (en realidad se llama Paquete de mensajes - Los paquetes tienden a utilizar MsgPack) es un formato binario, orientado a la compatibilidad con JSON, pero disminuyendo el tamaño del archivo (lo que es bueno para ahorrar ancho de banda y recursos del servidor).

Otra ventaja: MessagePack permite incrustar datos binarios (hay algunos casos de uso interesantes previstos para PiCockpit v2.1+).

En comparación con otros formatos de serialización binaria (por ejemplo, BSON), MsgPack busca una mayor compatibilidad con JSON y es más compacto, y puede ser decodificado como un flujo!

Mensajes retenidos del pasado

Sin embargo, debido a que los mensajes retenidos siguen estando en JSON (y a que los clientes heredados siguen enviando mensajes JSON), es necesario proporcionar compatibilidad con versiones anteriores, especialmente en el lado de JavaScript.

Si no se proporciona compatibilidad con versiones anteriores, se producirán los siguientes problemas con Paho:

onConnectFailure;Falló la conexión MQTT (5): AMQJS0005E Error interno. Mensaje de error: AMQJS0009E Datos UTF mal formados:ad -4f ., Stack trace: No hay pila de error disponible

onConnectFailure;Falló la conexión MQTT (5): AMQJS0005E Error interno. Mensaje de error: Extra 231 byte(s) encontrados en el buffer[1], Stack trace: No hay pila de error disponible

Codificación para el retorno a JSON

Paho no nos da acceso a los datos de los mensajes que tiene en sus estructuras (ver Código Paho aquí).

Por lo tanto, podemos recurrir a la captura de excepciones, asumiendo que el mensaje estará muy probablemente en el formato MsgPack, y si la decodificación que falla, cambiará a JSON.

Y si la decodificación de JSON falla, proporcionamos un fallback {} contra el fuzzing:

extractMessage(message){
     // 20.7.2020: cambiar a msgPack; tiene que ser payloadBytes, no payloadString
     var decodedMessage = {};
     intentar {
         decodedMessage = decode(message.payloadBytes);
     }
     catch (e){
         console.log("se ha detectado un error de decodificación ");
         console.log(e);
         intentar {
             decodedMessage = JSON.parse(message.payloadString);
         }
         catch (e){
             console.log("mensaje malformado (ni JSON ni MsgPack) - interpretando como objeto vacío {}");
         }
     }
     devolver el mensaje decodificado;
     // devolver JSON.parse(message.payloadString);
}

imagen

  • nota que usamos payloadBytes para acceder al mensaje para msgPack, y payloadString para decodificar JSON
  • Obsérvese que la decodificación (y la codificación) se incluyen así: import { encode, decode } from "@msgpack/msgpack"; en mi flujo de trabajo de Webpack

Referencias