{"id":27450,"date":"2020-07-21T13:10:57","date_gmt":"2020-07-21T11:10:57","guid":{"rendered":"https:\/\/pi3g.com\/?p=27450"},"modified":"2020-07-21T13:10:57","modified_gmt":"2020-07-21T11:10:57","slug":"switching-from-json-to-msgpack-in-a-backwards-compatible-manner-with-paho-mqtt-javascript","status":"publish","type":"post","link":"https:\/\/pi3g.com\/de\/switching-from-json-to-msgpack-in-a-backwards-compatible-manner-with-paho-mqtt-javascript\/","title":{"rendered":"Umstellung von JSON auf MsgPack in einer r\u00fcckw\u00e4rtskompatiblen Weise mit Paho MQTT (JavaScript)"},"content":{"rendered":"<p><a href=\"https:\/\/picockpit.com\">picockpit.com<\/a> makes heavy use of MQTT. For the upcoming version 2.0 I have decided to switch it to MsgPack.<\/p>\n<h1>Why MsgPack?<\/h1>\n<p>MsgPack (actually called <a href=\"https:\/\/msgpack.org\/index.html\">MessagePack<\/a> \u2013 packages tend to use MsgPack) is a binary format, aimed at compatibility with JSON, but decreasing file size (which is good for saving bandwidth &amp; server resources).<\/p>\n<p>Another advantage: MessagePack <strong>allows you to embed binary data <\/strong>(there\u2019s some exciting use cases planned for PiCockpit v2.1+). <\/p>\n<p>Compared to other Binary serialization formats (e.g. BSON) MsgPack aims for more compatibility with JSON, is more compact, <strong>and can be decoded as a stream<\/strong>!<\/p>\n<h1>Retained Messages from the past<\/h1>\n<p>Due to retained messages still being in JSON (and also legacy clients still sending JSON messages), however, backwards compatibility needs to be provided, especially on the JavaScript side.<\/p>\n<p>Failing to provide backwards compatibility will lead to the following problems with Paho:<\/p>\n<p><b>onConnectFailure;MQTT connection failed (5): AMQJS0005E Internal error. Error Message: AMQJS0009E Malformed UTF data:ad -4f ., Stack trace: No Error Stack Available<\/b><\/p>\n<p><b>onConnectFailure;MQTT connection failed (5): AMQJS0005E Internal error. Error Message: Extra 231 byte(s) found at buffer[1], Stack trace: No Error Stack Available<\/b><\/p>\n<h1>Coding for fallback to JSON<\/h1>\n<p>Paho does not give us access to the message data itself it has in it\u2019s structures (see <a href=\"https:\/\/www.eclipse.org\/paho\/files\/jsdoc\/paho-mqtt.js.html#line2283\">Paho code here<\/a>).<\/p>\n<p>Therefore we can fall back to exception catching, assuming that the message will most likely be in the MsgPack format, and if decoding that fails, will switch to JSON. <\/p>\n<p>And if decoding JSON fails, we provide a {} fallback against fuzzing:<\/p>\n<blockquote>\n<p>extractMessage(message){<br \/>&nbsp;&nbsp;&nbsp;&nbsp; \/\/ 20.7.2020: switch to msgPack; has to be payloadBytes, not payloadString<br \/>&nbsp;&nbsp;&nbsp;&nbsp; var decodedMessage = {};<br \/>&nbsp;&nbsp;&nbsp;&nbsp; try {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decodedMessage = decode(message.payloadBytes);<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp; catch (e){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(&#8220;decode error caught &#8220;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(e);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decodedMessage = JSON.parse(message.payloadString);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (e){<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(&#8220;malformed message (neither JSON nor MsgPack) &#8211; interpreting as empty object {}&#8221;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp; }<br \/>&nbsp;&nbsp;&nbsp;&nbsp; return decodedMessage;<br \/>&nbsp;&nbsp;&nbsp;&nbsp; \/\/ return JSON.parse(message.payloadString);<br \/>\n}<\/p>\n<\/blockquote>\n<p>\n<a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/07\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"719\" height=\"281\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/07\/image_thumb-3.png\" border=\"0\"><\/a><\/p>\n<ul>\n<li>note that we use payloadBytes to access the message for msgPack, and payloadString for JSON decoding<\/li>\n<li>note that decode (and encode) are included like this: <em>import { encode, decode } from &#8220;@msgpack\/msgpack&#8221;; <\/em>in my Webpack Workflow<\/li>\n<\/ul>\n<h1>References<\/h1>\n<ul>\n<li><a href=\"https:\/\/msgpack.org\/index.html\">MessagePack (msgpack.org)<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/msgpack\/msgpack-javascript\">msgpack JavaScript library<\/a> (use this one instead of the one linked on msgpack.org, as it has more recent activity)<\/li>\n<li><a href=\"https:\/\/www.eclipse.org\/paho\/files\/jsdoc\/paho-mqtt.js.html#line2283\">Paho MQTT JS Source Code<\/a><\/li>\n<li><a href=\"https:\/\/www.eclipse.org\/paho\/files\/jsdoc\/Paho.MQTT.Message.html\">Paho MQTT JS Documentation for the Class Message<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>picockpit.com macht regen Gebrauch von MQTT. F\u00fcr die kommende Version 2.0 habe ich mich entschieden, auf MsgPack umzusteigen. Warum MsgPack? MsgPack (eigentlich MessagePack genannt - Pakete verwenden in der Regel MsgPack) ist ein bin\u00e4res Format, das auf Kompatibilit\u00e4t mit JSON abzielt, aber die Dateigr\u00f6\u00dfe verringert (was gut f\u00fcr die Einsparung von Bandbreite und Serverressourcen ist). Ein weiterer Vorteil:...<\/p>","protected":false},"author":830,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[822,636],"tags":[827,828,826,829,600,670,824,823,825],"class_list":["post-27450","post","type-post","status-publish","format-standard","hentry","category-javascript","category-mqtt","tag-amqjs0005e-internal-error","tag-amqjs0009e-malformed-utf-data","tag-error","tag-extra-231-bytes-found-at-buffer1","tag-javascript","tag-json","tag-msgpack","tag-paho-mqtt","tag-serialization"],"_links":{"self":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27450","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/users\/830"}],"replies":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/comments?post=27450"}],"version-history":[{"count":1,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27450\/revisions"}],"predecessor-version":[{"id":27451,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27450\/revisions\/27451"}],"wp:attachment":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media?parent=27450"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/categories?post=27450"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/tags?post=27450"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}