2017-04-24 13:22:55 +02:00
|
|
|
/** Javascript class for parsing binary messages.
|
|
|
|
*
|
|
|
|
* Note: Messages sent by the 'websocket' node-type are always send in little endian byte-order!
|
|
|
|
* This is different from the messages send with the 'socket' node-type!
|
2016-01-14 23:17:39 +01:00
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2020-01-20 17:17:00 +01:00
|
|
|
* @copyright 2014-2020, Institute for Automation of Complex Power Systems, EONERC
|
2017-04-27 12:56:43 +02:00
|
|
|
* @license GNU General Public License (version 3)
|
|
|
|
*
|
|
|
|
* VILLASnode
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* any later version.
|
2017-05-05 19:24:16 +00:00
|
|
|
*
|
2017-04-27 12:56:43 +02:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2017-05-05 19:24:16 +00:00
|
|
|
*
|
2017-04-27 12:56:43 +02:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2016-11-22 11:14:25 -05:00
|
|
|
*********************************************************************************/
|
2017-04-27 13:08:17 +02:00
|
|
|
|
2016-01-14 23:17:39 +01:00
|
|
|
/**
|
|
|
|
* @addtogroup websocket
|
|
|
|
* @ingroup node
|
|
|
|
* @{
|
2017-04-27 13:08:17 +02:00
|
|
|
*/
|
2016-01-14 23:17:39 +01:00
|
|
|
|
2016-07-12 12:47:50 +02:00
|
|
|
/* Class for parsing and printing a message */
|
2017-04-07 17:24:51 +02:00
|
|
|
function Msg(c)
|
2016-07-12 12:47:50 +02:00
|
|
|
{
|
|
|
|
this.sequence = typeof c.sequence === 'undefined' ? 0 : c.sequence;
|
|
|
|
this.length = typeof c.length === 'undefined' ? 0 : c.length;
|
|
|
|
this.version = typeof c.version === 'undefined' ? Msg.prototype.VERSION : c.version;
|
|
|
|
this.type = typeof c.type === 'undefined' ? Msg.prototype.TYPE_DATA : c.type;
|
|
|
|
this.timestamp = typeof c.timestamp === 'undefined' ? Date.now() : c.timestamp;
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2017-04-07 17:24:51 +02:00
|
|
|
if (Array.isArray(c.data)) {
|
|
|
|
this.length = c.data.length;
|
|
|
|
this.data = c.data;
|
2016-07-12 12:47:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 16:28:31 +01:00
|
|
|
/* Some constants for the binary protocol */
|
2017-08-27 17:07:33 +02:00
|
|
|
Msg.prototype.VERSION = 2;
|
2016-02-04 16:28:31 +01:00
|
|
|
|
2017-08-27 17:07:33 +02:00
|
|
|
Msg.prototype.TYPE_DATA = 0; /**< Message contains float values */
|
2016-02-04 16:28:31 +01:00
|
|
|
|
|
|
|
/* Some offsets in the binary message */
|
2017-08-27 17:07:33 +02:00
|
|
|
Msg.prototype.OFFSET_TYPE = 2;
|
|
|
|
Msg.prototype.OFFSET_VERSION = 4;
|
2016-02-04 16:28:31 +01:00
|
|
|
|
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-01-14 23:17:39 +01:00
|
|
|
|
|
|
|
var msg = new Msg({
|
2016-07-12 12:47:50 +02:00
|
|
|
version: (bits >> Msg.prototype.OFFSET_VERSION) & 0xF,
|
|
|
|
type: (bits >> Msg.prototype.OFFSET_TYPE) & 0x3,
|
2017-04-24 13:22:55 +02:00
|
|
|
id: data.getUint8( 0x01),
|
|
|
|
length: data.getUint16(0x02, 1),
|
|
|
|
sequence: data.getUint32(0x04, 1),
|
|
|
|
timestamp: data.getUint32(0x08, 1) * 1e3 +
|
|
|
|
data.getUint32(0x0C, 1) * 1e-6,
|
2016-01-14 23:17:39 +01:00
|
|
|
});
|
2017-05-05 19:24:16 +00: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
|
|
|
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));
|
2017-05-05 19:24:16 +00: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);
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
var bits = 0;
|
2016-07-12 12:47:50 +02:00
|
|
|
bits |= (this.version & 0xF) << Msg.prototype.OFFSET_VERSION;
|
|
|
|
bits |= (this.type & 0x3) << Msg.prototype.OFFSET_TYPE;
|
2017-05-05 19:24:16 +00:00
|
|
|
|
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;
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
view.setUint8( 0x00, bits, true);
|
|
|
|
view.setUint16(0x02, this.length, true);
|
|
|
|
view.setUint32(0x04, this.sequence, true);
|
|
|
|
view.setUint32(0x08, sec, true);
|
|
|
|
view.setUint32(0x0C, nsec, true);
|
2017-05-05 19:24:16 +00:00
|
|
|
|
2016-07-11 18:19:48 +02:00
|
|
|
data = new Float32Array(buffer, 0x10, this.length);
|
|
|
|
data.set(this.data);
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2016-01-14 23:17:39 +01:00
|
|
|
/** @} */
|