mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-30 00:00:13 +01:00
164 lines
4.8 KiB
JavaScript
164 lines
4.8 KiB
JavaScript
/**
|
|
* This file is part of VILLASweb.
|
|
*
|
|
* VILLASweb 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
|
|
* (at your option) any later version.
|
|
*
|
|
* VILLASweb 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 VILLASweb. If not, see <http://www.gnu.org/licenses/>.
|
|
******************************************************************************/
|
|
|
|
import WebsocketAPI from '../common/api/websocket-api';
|
|
import AppDispatcher from '../common/app-dispatcher';
|
|
|
|
const OFFSET_TYPE = 2;
|
|
const OFFSET_VERSION = 4;
|
|
|
|
class IcDataDataManager {
|
|
constructor() {
|
|
this._sockets = {};
|
|
}
|
|
|
|
open(websocketurl, identifier) {
|
|
// pass signals to onOpen callback
|
|
if (this._sockets[identifier] != null)
|
|
return; // already open?
|
|
|
|
this._sockets[identifier] = new WebsocketAPI(websocketurl, { onOpen: (event) => this.onOpen(event, identifier, true), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) });
|
|
}
|
|
|
|
update(websocketurl, identifier) {
|
|
if (this._sockets[identifier] != null) {
|
|
if (this._sockets[identifier].websocketurl !== websocketurl) {
|
|
this._sockets[identifier].close();
|
|
this._sockets[identifier] = new WebsocketAPI(websocketurl, { onOpen: (event) => this.onOpen(event, identifier, false), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier), onError: (error) => this.onError(error, identifier) });
|
|
}
|
|
}
|
|
}
|
|
|
|
closeAll() {
|
|
// close every open socket
|
|
for (var identifier in this._sockets) {
|
|
if (this._sockets.hasOwnProperty(identifier)) {
|
|
this._sockets[identifier].close(4000);
|
|
delete this._sockets[identifier];
|
|
}
|
|
}
|
|
}
|
|
|
|
send(message, identifier) {
|
|
const socket = this._sockets[identifier];
|
|
if (socket == null) {
|
|
return false;
|
|
}
|
|
console.log("Sending to IC", identifier, "message: ", message);
|
|
const data = this.messageToBuffer(message);
|
|
socket.send(data);
|
|
|
|
return true;
|
|
}
|
|
|
|
onOpen(event, identifier, firstOpen) {
|
|
AppDispatcher.dispatch({
|
|
type: 'icData/opened',
|
|
id: identifier,
|
|
firstOpen: firstOpen
|
|
});
|
|
}
|
|
|
|
onClose(event, identifier) {
|
|
AppDispatcher.dispatch({
|
|
type: 'icData/closed',
|
|
id: identifier,
|
|
notification: (event.code !== 4000)
|
|
});
|
|
|
|
// remove from list, keep null reference for flag detection
|
|
delete this._sockets[identifier];
|
|
}
|
|
|
|
onMessage(event, identifier) {
|
|
var msgs = this.bufferToMessageArray(event.data);
|
|
|
|
if (msgs.length > 0) {
|
|
AppDispatcher.dispatch({
|
|
type: 'icData/data-changed',
|
|
data: msgs,
|
|
id: identifier
|
|
});
|
|
}
|
|
}
|
|
|
|
bufferToMessage(data) {
|
|
// parse incoming message into usable data
|
|
if (data.byteLength === 0) {
|
|
return null;
|
|
}
|
|
|
|
const id = data.getUint8(1);
|
|
const bits = data.getUint8(0);
|
|
const length = data.getUint16(0x02, 1);
|
|
const bytes = length * 4 + 16;
|
|
|
|
return {
|
|
version: (bits >> OFFSET_VERSION) & 0xF,
|
|
type: (bits >> OFFSET_TYPE) & 0x3,
|
|
length: length,
|
|
sequence: data.getUint32(0x04, 1),
|
|
timestamp: data.getUint32(0x08, 1) * 1e3 + data.getUint32(0x0C, 1) * 1e-6,
|
|
values: new Float32Array(data.buffer, data.byteOffset + 0x10, length),
|
|
blob: new DataView(data.buffer, data.byteOffset + 0x00, bytes),
|
|
id: id
|
|
};
|
|
}
|
|
|
|
bufferToMessageArray(blob) {
|
|
/* some local variables for parsing */
|
|
let offset = 0;
|
|
const msgs = [];
|
|
|
|
/* for every msg in vector */
|
|
while (offset < blob.byteLength) {
|
|
const msg = this.bufferToMessage(new DataView(blob, offset));
|
|
|
|
if (msg !== undefined) {
|
|
msgs.push(msg);
|
|
offset += msg.blob.byteLength;
|
|
}
|
|
}
|
|
|
|
return msgs;
|
|
}
|
|
|
|
messageToBuffer(message) {
|
|
const buffer = new ArrayBuffer(16 + 4 * message.length);
|
|
const view = new DataView(buffer);
|
|
|
|
let bits = 0;
|
|
bits |= (message.version & 0xF) << OFFSET_VERSION;
|
|
bits |= (message.type & 0x3) << OFFSET_TYPE;
|
|
|
|
const sec = Math.floor(message.timestamp / 1e3);
|
|
const nsec = (message.timestamp - sec * 1e3) * 1e6;
|
|
|
|
view.setUint8(0x00, bits, true);
|
|
view.setUint16(0x02, message.length, true);
|
|
view.setUint32(0x04, message.sequence, true);
|
|
view.setUint32(0x08, sec, true);
|
|
view.setUint32(0x0C, nsec, true);
|
|
|
|
const data = new Float32Array(buffer, 0x10, message.length);
|
|
data.set(message.values);
|
|
|
|
return buffer;
|
|
}
|
|
}
|
|
|
|
export default new IcDataDataManager();
|