/** 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! * * @file * @author Steffen Vogel * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC * @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. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . *********************************************************************************/ /** * @addtogroup websocket * @ingroup node * @{ */ /* Class for parsing and printing a message */ function Msg(c) { 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; if (Array.isArray(c.data)) { this.length = c.data.length; this.data = c.data; } } /* Some constants for the binary protocol */ Msg.prototype.VERSION = 2; Msg.prototype.TYPE_DATA = 0; /**< Message contains float values */ /* Some offsets in the binary message */ Msg.prototype.OFFSET_TYPE = 2; Msg.prototype.OFFSET_VERSION = 4; Msg.bytes = function(len) { return len * 4 + 16; } Msg.fromArrayBuffer = function(data) { var bits = data.getUint8(0); var msg = new Msg({ version: (bits >> Msg.prototype.OFFSET_VERSION) & 0xF, type: (bits >> Msg.prototype.OFFSET_TYPE) & 0x3, 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, }); msg.blob = new DataView( data.buffer, data.byteOffset + 0x00, Msg.bytes(msg.length)); msg.data = new Float32Array(data.buffer, data.byteOffset + 0x10, msg.length); return msg; } Msg.fromArrayBufferVector = function(blob) { /* some local variables for parsing */ var offset = 0; var msgs = []; /* for every msg in vector */ while (offset < blob.byteLength) { var msg = Msg.fromArrayBuffer(new DataView(blob, offset)); if (msg != undefined) { msgs.push(msg); offset += msg.blob.byteLength; } } return msgs; } Msg.prototype.toArrayBuffer = function() { buffer = new ArrayBuffer(Msg.bytes(this.length)) view = new DataView(buffer); var bits = 0; bits |= (this.version & 0xF) << Msg.prototype.OFFSET_VERSION; bits |= (this.type & 0x3) << Msg.prototype.OFFSET_TYPE; var sec = Math.floor(this.timestamp / 1e3); var nsec = (this.timestamp - sec * 1e3) * 1e6; 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); data = new Float32Array(buffer, 0x10, this.length); data.set(this.data); return buffer; } /** @} */