overschakelen van JSON naar MsgPack op een achterwaartse compatibele manier met Paho MQTT (JavaScript)

picockpit.com maakt zwaar gebruik van MQTT. Voor de komende versie 2.0 heb ik besloten om over te schakelen op MsgPack.

Waarom MsgPack?

MsgPack (eigenlijk genaamd MessagePack - pakketten gebruiken meestal MsgPack) is een binair formaat, gericht op compatibiliteit met JSON, maar met een kleinere bestandsgrootte (wat goed is om bandbreedte en serverbronnen te besparen).

Nog een voordeel: MessagePack kunt u binaire gegevens insluiten (er zijn enkele opwindende gebruiksscenario's gepland voor PiCockpit v2.1+).

Vergeleken met andere binaire serialiseringsformaten (bv. BSON) streeft MsgPack naar meer compatibiliteit met JSON en is het compacter, en kan worden gedecodeerd als een stroom!

Behouden berichten uit het verleden

Omdat bewaarde berichten nog steeds in JSON zijn (en oudere clients nog steeds JSON-berichten verzenden), moet echter worden gezorgd voor achterwaartse compatibiliteit, vooral aan de JavaScript-zijde.

Het niet bieden van achterwaartse compatibiliteit zal leiden tot de volgende problemen met Paho:

onConnectFailure;MQTT-verbinding mislukt (5): AMQJS0005E Interne fout. Foutmelding: AMQJS0009E Misvormde UTF-gegevens:ad -4f ., Stack trace: Geen fout stack beschikbaar

onConnectFailure;MQTT-verbinding mislukt (5): AMQJS0005E Interne fout. Foutmelding: Extra 231 byte(s) gevonden bij buffer[1], Stack trace: Geen fout stack beschikbaar

Codering voor fallback naar JSON

Paho geeft ons geen toegang tot de berichtgegevens zelf die het in zijn structuren heeft (zie Paho code hier).

Daarom kunnen we terugvallen op het opvangen van uitzonderingen, ervan uitgaande dat het bericht hoogstwaarschijnlijk in het MsgPack formaat zal zijn, en als het decoderen daarvan mislukt, zullen we overschakelen op JSON.

En als het decoderen van JSON mislukt, voorzien we een {} fallback tegen fuzzing:

extractMessage(bericht){
     // 20.7.2020: schakel over naar msgPack; moet payloadBytes zijn, niet payloadString
     var gedecodeerd bericht = {};
     probeer {
         gedecodeerdBericht = decoderen(bericht.payloadBytes);
     }
     catch (e){
         console.log("decodeer fout gevangen ");
         console.log(e);
         probeer {
             gedecodeerd bericht = JSON.parse(message.payloadString);
         }
         catch (e){
             console.log("misvormd bericht (noch JSON, noch MsgPack) - interpreteren als leeg object {}");
         }
     }
     geef gedecodeerd bericht terug;
     // JSON.parse(message.payloadString) teruggeven;
}

afbeelding

  • Merk op dat we payloadBytes gebruiken om toegang te krijgen tot het bericht voor msgPack, en payloadString voor JSON decodering
  • Merk op dat decode (en encode) als volgt zijn opgenomen: importeer { encode, decode } uit "@msgpack/msgpack"; in mijn Webpack Workflow

Referenties