passage de JSON à MsgPack de manière rétrocompatible avec Paho MQTT (JavaScript)

picockpit.com fait un usage intensif de MQTT. Pour la prochaine version 2.0, j'ai décidé de passer à MsgPack.

Pourquoi MsgPack ?

MsgPack (appelé en réalité MessagePack - ont tendance à utiliser MsgPack) est un format binaire, visant la compatibilité avec JSON, mais diminuant la taille du fichier (ce qui est bon pour économiser la bande passante et les ressources du serveur).

Un autre avantage : MessagePack permet d'intégrer des données binaires (des cas d'utilisation passionnants sont prévus pour PiCockpit v2.1+).

Par rapport à d'autres formats de sérialisation binaire (par exemple BSON), MsgPack vise une plus grande compatibilité avec JSON et est plus compact, et peut être décodé comme un flux!

Messages conservés du passé

Toutefois, étant donné que les messages conservés sont toujours en JSON (et que les anciens clients envoient toujours des messages en JSON), il faut assurer la rétrocompatibilité, en particulier du côté de JavaScript.

Le fait de ne pas assurer la rétrocompatibilité entraînera les problèmes suivants avec Paho :

onConnectFailure;La connexion MQTT a échoué (5) : AMQJS0005E Erreur interne. Message d'erreur : AMQJS0009E Données UTF malformées : ad -4f ., Trace de pile : Aucune pile d'erreur disponible

onConnectFailure;La connexion MQTT a échoué (5) : AMQJS0005E Erreur interne. Message d'erreur : Extra 231 byte(s) found at buffer[1], Stack trace : Aucune pile d'erreur disponible

Codage pour le repli vers JSON

Paho ne nous donne pas accès aux données des messages qu'il a lui-même dans ses structures (cf. Code Paho ici).

Par conséquent, nous pouvons nous rabattre sur la capture des exceptions, en supposant que le message sera très probablement au format MsgPack, et si le décodage échoue, nous passerons à JSON.

Et si le décodage de JSON échoue, nous fournissons une solution de repli {} contre le fuzzing :

extractMessage(message){
     // 20.7.2020 : passage à msgPack ; doit être payloadBytes et non payloadString.
     var decodedMessage = {} ;
     essayez {
         Message décodé = décoder(message.payloadBytes) ;
     }
     catch (e){
         console.log("erreur de décodage détectée ") ;
         console.log(e) ;
         essayez {
             message décodé = JSON.parse(message.payloadString) ;
         }
         catch (e){
             console.log("message malformé (ni JSON ni MsgPack) - interprété comme un objet vide {}") ;
         }
     }
     retourner le message décodé ;
     // retourner JSON.parse(message.payloadString) ;
}

image

  • Notez que nous utilisons payloadBytes pour accéder au message pour msgPack, et payloadString pour le décodage JSON.
  • Notez que decode (et encode) sont inclus comme ceci : import { encode, decode } de "@msgpack/msgpack" ; dans mon flux de travail Webpack

Références