2016-01-14 23:17:39 +01:00
|
|
|
/** Javascript class for parsing binary messages
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2016-11-22 11:14:25 -05:00
|
|
|
* @copyright 2016, Institute for Automation of Complex Power Systems, EONERC
|
|
|
|
*********************************************************************************/
|
2016-01-14 23:17:39 +01:00
|
|
|
/**
|
|
|
|
* @addtogroup websocket
|
|
|
|
* @ingroup node
|
|
|
|
* @{
|
2016-11-22 11:14:25 -05:00
|
|
|
*********************************************************************************/
|
2016-01-14 23:17:39 +01:00
|
|
|
|
2016-07-12 12:47:50 +02:00
|
|
|
/* Class for parsing and printing a message */
|
|
|
|
function Msg(c, d)
|
|
|
|
{
|
|
|
|
this.sequence = typeof c.sequence === 'undefined' ? 0 : c.sequence;
|
|
|
|
this.length = typeof c.length === 'undefined' ? 0 : c.length;
|
|
|
|
this.endian = typeof c.endian === 'undefined' ? Msg.prototype.ENDIAN_LITTLE : c.endian;
|
|
|
|
this.version = typeof c.version === 'undefined' ? Msg.prototype.VERSION : c.version;
|
|
|
|
this.type = typeof c.type === 'undefined' ? Msg.prototype.TYPE_DATA : c.type;
|
2016-11-07 21:30:28 -05:00
|
|
|
this.id = typeof c.id === 'undefined' ? -1 : c.id;
|
2016-07-12 12:47:50 +02:00
|
|
|
this.timestamp = typeof c.timestamp === 'undefined' ? Date.now() : c.timestamp;
|
|
|
|
|
|
|
|
if (Array.isArray(d)) {
|
|
|
|
this.length = d.length;
|
|
|
|
this.data = d
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
/* Some constants for the binary protocol */
|
|
|
|
Msg.prototype.VERSION = 1;
|
|
|
|
|
|
|
|
Msg.prototype.TYPE_DATA = 0; /**< Message contains float values */
|
|
|
|
|
|
|
|
Msg.prototype.ENDIAN_LITTLE = 0; /**< Message values are in little endian format (float too!) */
|
|
|
|
Msg.prototype.ENDIAN_BIG = 1; /**< Message values are in bit endian format */
|
|
|
|
|
|
|
|
/* Some offsets in the binary message */
|
|
|
|
Msg.prototype.OFFSET_ENDIAN = 1;
|
|
|
|
Msg.prototype.OFFSET_TYPE = 2;
|
|
|
|
Msg.prototype.OFFSET_VERSION = 4;
|
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
Msg.bytes = function(len)
|
|
|
|
{
|
|
|
|
return len * 4 + 16;
|
2016-01-14 23:17:39 +01:00
|
|
|
}
|
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
Msg.fromArrayBuffer = function(data)
|
|
|
|
{
|
2016-02-04 16:28:31 +01:00
|
|
|
var bits = data.getUint8(0);
|
2016-07-12 12:47:50 +02:00
|
|
|
var endian = (bits >> Msg.prototype.OFFSET_ENDIAN) & 0x1 ? 0 : 1;
|
2016-01-14 23:17:39 +01:00
|
|
|
|
|
|
|
var msg = new Msg({
|
2016-07-12 12:47:50 +02:00
|
|
|
endian: (bits >> Msg.prototype.OFFSET_ENDIAN) & 0x1,
|
|
|
|
version: (bits >> Msg.prototype.OFFSET_VERSION) & 0xF,
|
|
|
|
type: (bits >> Msg.prototype.OFFSET_TYPE) & 0x3,
|
2016-11-07 21:30:28 -05:00
|
|
|
id: data.getUint8( 0x01, endian),
|
2016-07-11 18:19:48 +02:00
|
|
|
length: data.getUint16(0x02, endian),
|
2016-02-04 16:28:31 +01:00
|
|
|
sequence: data.getUint32(0x04, endian),
|
|
|
|
timestamp: data.getUint32(0x08, endian) * 1e3 +
|
|
|
|
data.getUint32(0x0C, endian) * 1e-6,
|
2016-01-14 23:17:39 +01:00
|
|
|
});
|
2016-02-04 16:28:31 +01:00
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
msg.blob = new DataView( data.buffer, data.byteOffset + 0x00, Msg.bytes(msg.length));
|
|
|
|
msg.data = new Float32Array(data.buffer, data.byteOffset + 0x10, msg.length);
|
2016-01-14 23:17:39 +01:00
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
if (msg.endian != host_endianess()) {
|
|
|
|
console.warn("Message is not given in host endianess!");
|
2016-01-14 23:17:39 +01:00
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
var data = new Uint32Array(msg.blob, 0x10);
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
data[i] = swap32(data[i]);
|
2016-01-14 23:17:39 +01:00
|
|
|
}
|
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
return msg;
|
2016-01-14 23:17:39 +01:00
|
|
|
}
|
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
Msg.fromArrayBufferVector = function(blob)
|
|
|
|
{
|
2016-01-14 23:17:39 +01:00
|
|
|
/* some local variables for parsing */
|
|
|
|
var offset = 0;
|
|
|
|
var msgs = [];
|
|
|
|
|
|
|
|
/* for every msg in vector */
|
2016-02-04 16:28:31 +01:00
|
|
|
while (offset < blob.byteLength) {
|
|
|
|
var msg = Msg.fromArrayBuffer(new DataView(blob, offset));
|
2016-01-14 23:17:39 +01:00
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
if (msg != undefined) {
|
2016-01-14 23:17:39 +01:00
|
|
|
msgs.push(msg);
|
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
offset += msg.blob.byteLength;
|
|
|
|
}
|
2016-01-14 23:17:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return msgs;
|
|
|
|
}
|
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
Msg.prototype.toArrayBuffer = function()
|
|
|
|
{
|
|
|
|
buffer = new ArrayBuffer(Msg.bytes(this.length))
|
|
|
|
view = new DataView(buffer);
|
|
|
|
|
|
|
|
var bits = 0;
|
2016-07-12 12:47:50 +02:00
|
|
|
bits |= (this.endian & 0x1) << Msg.prototype.OFFSET_ENDIAN;
|
|
|
|
bits |= (this.version & 0xF) << Msg.prototype.OFFSET_VERSION;
|
|
|
|
bits |= (this.type & 0x3) << Msg.prototype.OFFSET_TYPE;
|
2016-07-11 18:19:48 +02:00
|
|
|
|
|
|
|
var sec = Math.floor(this.timestamp / 1e3);
|
2016-07-12 12:47:50 +02:00
|
|
|
var nsec = (this.timestamp - sec * 1e3) * 1e6;
|
2016-07-11 18:19:48 +02:00
|
|
|
|
|
|
|
view.setUint8( 0x00, bits, true);
|
2016-11-07 21:30:28 -05:00
|
|
|
view.setUint8( 0x01, this.id, true);
|
2016-07-11 18:19:48 +02:00
|
|
|
view.setUint16(0x02, this.length, true);
|
|
|
|
view.setUint32(0x04, this.sequence, true);
|
|
|
|
view.setUint32(0x08, sec, true);
|
|
|
|
view.setUint32(0x0C, nsec, true);
|
|
|
|
|
|
|
|
data = new Float32Array(buffer, 0x10, this.length);
|
|
|
|
data.set(this.data);
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2016-01-14 23:17:39 +01:00
|
|
|
/** @todo parsing of big endian messages not yet supported */
|
2016-07-11 18:19:48 +02:00
|
|
|
function swap16(val)
|
|
|
|
{
|
2016-01-14 23:17:39 +01:00
|
|
|
return ((val & 0xFF) << 8)
|
|
|
|
| ((val >> 8) & 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
function swap32(val) {
|
|
|
|
return ((val & 0xFF) << 24)
|
|
|
|
| ((val & 0xFF00) << 8)
|
|
|
|
| ((val >> 8) & 0xFF00)
|
|
|
|
| ((val >> 24) & 0xFF);
|
|
|
|
}
|
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
function host_endianess() {
|
|
|
|
var buffer = new ArrayBuffer(2);
|
|
|
|
new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
|
|
|
|
return new Int16Array(buffer)[0] === 256 ? 0 : 1; // Int16Array uses the platform's endianness.
|
|
|
|
};
|
|
|
|
|
2016-01-14 23:17:39 +01:00
|
|
|
/** @} */
|