1

I'm using the paho: http://www.eclipse.org/paho/clients/js/ lib to connect to a mqtt-broker. But when I receive binary-data via websockets, it says my data is malformed: Error: AMQJS0009E Malformed UTF data:d4 -3f . . Isn't it possible to receive binary with paho mqttws31.js

Edit: Unfortunately I used (message.payloadString) to get the received message. But as far as I can understand(https://github.com/i5ting/paho.mqtt.javascript/blob/master/src/mqttws31.js#L2060) one can also use message.payloadBytes.

So actually I'm sending Doubles, each has 8bytes. How can I access them within message.payloadBytes?

Thx.

dan kutz
  • 107
  • 1
  • 12

1 Answers1

3

You probably want to have a look at this:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays

From this it looks like you should be able to do something like this:

var payload = message.payloadByte()
var doubleView = new Float64Array(payload);
var number = doubleView[0];

This assumes that the payload of the message is a single 64-bit IEEE floating point number

The other possible option is to look at the answer to this previous question :

Read/Write bytes of float in JS

EDIT:

The following code works for me:

function onMessageArrived(message) {
  var payload = message.payloadBytes
  var length = payload.length;
  var buffer = new ArrayBuffer(length);
  uint = new Uint8Array(buffer);
  for (var i=0; i<length; i++) {
      uint[(length-1)-i] = payload[i];
  }
  var doubleView = new Float64Array(uint.buffer);
  var number = doubleView[0];
  console.log("onMessageArrived:"+number);
};

Note that I had to reverse the byte order to get the correct output.

EDIT 2

This works better and will decode arbitrary lengths of arrays of doubles:

function onMessageArrived(message) {
  var payload = message.payloadBytes
  var length = payload.length;
  var buffer = new ArrayBuffer(length);
  uint = new Uint8Array(buffer);
  for (var i=0; i<length; i++) {
      uint[i] = payload[i];
  }
  var dataView = new DataView(uint.buffer);
  for (var i=0; i<length/8; i++) {
      console.log(dataView.getFloat64((i*8), false));
  }
};

(you may need to flip the false to a true at the end of the dataView.getFloat64() depending on the endianness of the sending platform)

Full write up of the code I wrote to get this far can be found here: http://www.hardill.me.uk/wordpress/2014/08/29/unpacking-binary-data-from-mqtt-in-javascript/

Community
  • 1
  • 1
hardillb
  • 54,545
  • 11
  • 67
  • 105
  • Ok I think it's the following problem: I want to convert an Uint8Array[256] into an array of floats each element having 8bytes of length. So it is an array with a length of 32 values(256/8) each value is an Double/Float with 8 bytes. – dan kutz Aug 29 '14 at 16:58
  • Thanks a lot. This is part of an optimization within a local network and I received a performance gain of 20-30%. Because it's about half of the data send binary compared to JSON.strinify(data), may be really nice for huge amounts of data transfered on the internet. However I wonder if this code may be optimized as well, because it's two for loops and reserving twice the amount of memory. – dan kutz Aug 30 '14 at 10:43
  • so I guess this is the most effective way to receive the data? – dan kutz Sep 02 '14 at 19:45