mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
added new web socket HTML / JS code and new logo
This commit is contained in:
parent
3880abeb63
commit
8e255cf083
7 changed files with 333 additions and 78 deletions
|
@ -1,11 +1,11 @@
|
|||
// global variables
|
||||
var connection;
|
||||
var timer;
|
||||
|
||||
var seq = 0;
|
||||
|
||||
var currentNode;
|
||||
var nodes = [ ];
|
||||
var updateRate = 1.0 / 25;
|
||||
|
||||
var plotData = [];
|
||||
var plotOptions = {
|
||||
|
@ -17,8 +17,9 @@ var plotOptions = {
|
|||
}
|
||||
};
|
||||
|
||||
var xPast = 10*1000;
|
||||
var xFuture = 5*1000;
|
||||
var xDelta = 0.5*1000;
|
||||
var xPast = xDelta*0.9;
|
||||
var xFuture = xDelta*0.1;
|
||||
|
||||
$(document).on('ready', function() {
|
||||
$.getJSON('/nodes.json', function(data) {
|
||||
|
@ -46,30 +47,69 @@ $(document).on('ready', function() {
|
|||
wsConnect(wsUrl(currentNode.name), ["live"]);
|
||||
});
|
||||
|
||||
$('#play').click(function(e, ui) {
|
||||
wsConnect(wsUrl(currentNode.name), ["live"]);
|
||||
});
|
||||
|
||||
$('#pause').click(function(e, ui) {
|
||||
connection.close();
|
||||
});
|
||||
|
||||
$('#slider').slider({
|
||||
min : 0,
|
||||
max : 100,
|
||||
slide : onSliderMoved
|
||||
slide : function(e, ui) {
|
||||
var msg = new Msg({
|
||||
timestamp : Date.now(),
|
||||
sequence : seq++
|
||||
}, [ ui.value ]);
|
||||
|
||||
|
||||
var blob = msg.toArrayBuffer()
|
||||
connection.send(blob);
|
||||
}
|
||||
});
|
||||
|
||||
$('#timespan').slider({
|
||||
min : 200,
|
||||
max : 10000,
|
||||
value : xDelta,
|
||||
slide : function(e, ui) {
|
||||
plotUpdateWindow(ui.value);
|
||||
}
|
||||
});
|
||||
|
||||
$('#controls .buttons button').each(function(button) {
|
||||
$(button).addClass('on');
|
||||
|
||||
$(button).onClick(function(value) {
|
||||
var msg = new Msg({
|
||||
timestamp : Date.now(),
|
||||
sequence : seq++
|
||||
}, [ value ]);
|
||||
|
||||
connection.send(msg.toArrayBuffer());
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(plotUpdate, updateRate);
|
||||
plotUpdateWindow(10*1000); /* start plot refresh timer for 10sec window */
|
||||
});
|
||||
|
||||
$(window).on('beforeunload', wsDisconnect);
|
||||
$(window).on('beforeunload', function() {
|
||||
connection.close();
|
||||
});
|
||||
|
||||
function plotUpdateWindow(delta) {
|
||||
xDelta = delta
|
||||
xPast = xDelta*0.9;
|
||||
xFuture = xDelta*0.1;
|
||||
}
|
||||
|
||||
function plotUpdate() {
|
||||
var data = [];
|
||||
|
||||
// add data to arrays
|
||||
for (var i = 0; i < plotData.length; i++) {
|
||||
// remove old values
|
||||
while (plotData[i].length > 0 && plotData[i][0][0] < (Date.now() - xPast))
|
||||
plotData[i].shift()
|
||||
|
||||
var seriesOptions = nodes
|
||||
|
||||
data[i] = {
|
||||
|
@ -101,31 +141,28 @@ function plotUpdate() {
|
|||
$.plot('.plot-container div', data, $.extend(true, options, plotOptions));
|
||||
}
|
||||
|
||||
function wsDisconnect() {
|
||||
connection.close();
|
||||
|
||||
$('#connectionStatus')
|
||||
.text('Disconnected')
|
||||
.css('color', 'red');
|
||||
|
||||
plotData = [];
|
||||
}
|
||||
|
||||
function wsConnect(url, protocol) {
|
||||
connection = new WebSocket(url, protocol);
|
||||
connection.binaryType = 'arraybuffer';
|
||||
|
||||
|
||||
connection.onopen = function() {
|
||||
$('#connectionStatus')
|
||||
.text('Connected')
|
||||
.css('color', 'green');
|
||||
|
||||
timer = setInterval(plotUpdate, 1000.0 / 25);
|
||||
};
|
||||
|
||||
connection.onclose = function() {
|
||||
wsDisconnect();
|
||||
$('#connectionStatus')
|
||||
.text('Disconnected')
|
||||
.css('color', 'red');
|
||||
|
||||
clearInterval(timer);
|
||||
|
||||
setTimeout(wsConnect, 3000); // retry
|
||||
setTimeout(function() {
|
||||
wsConnect(wsUrl(currentNode.name), ["live"]);
|
||||
}, 1000); // retry
|
||||
};
|
||||
|
||||
connection.onerror = function(error) {
|
||||
|
@ -136,11 +173,19 @@ function wsConnect(url, protocol) {
|
|||
|
||||
connection.onmessage = function(e) {
|
||||
var msgs = Msg.fromArrayBufferVector(e.data);
|
||||
|
||||
console.log('Received ' + msgs.length + ' messages with ' + msgs[0].data.length + ' values: ' + msgs[0].timestamp);
|
||||
|
||||
for (var j = 0; j < plotData.length; j++) {
|
||||
// remove old values
|
||||
while (plotData[j].length > 0 && plotData[j][0][0] < (Date.now() - xPast))
|
||||
plotData[j].shift()
|
||||
}
|
||||
|
||||
for (var j = 0; j < msgs.length; j++) {
|
||||
var msg = msgs[j];
|
||||
|
||||
// add empty arrays for data
|
||||
// add empty arrays for data series
|
||||
while (plotData.length < msg.values)
|
||||
plotData.push([]);
|
||||
|
||||
|
@ -207,31 +252,6 @@ function fileStart(e) {
|
|||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
/* Control event handlers */
|
||||
function onButtonClick(value) {
|
||||
msg.values = [ value ];
|
||||
msg.ts = Date.now();
|
||||
msg.seq++;
|
||||
|
||||
msg.send(connection);
|
||||
}
|
||||
|
||||
function onTextChange(e) {
|
||||
msg.values = [ e.target.text ];
|
||||
msg.ts = Date.now();
|
||||
msg.seq++;
|
||||
|
||||
msg.send(connection);
|
||||
}
|
||||
|
||||
function onSliderMoved(e, ui) {
|
||||
msg.values = [ ui.value ];
|
||||
msg.ts = Date.now();
|
||||
msg.seq++;
|
||||
|
||||
msg.send(connection);
|
||||
}
|
||||
|
||||
/* Some helpers */
|
||||
function getParameterByName(name) {
|
||||
var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../doc/pictures/eonerc_logo.png
|
|
@ -8,7 +8,7 @@
|
|||
<link rel="stylesheet" href="jquery-ui/jquery-ui.structure.css" />
|
||||
|
||||
<script src="jquery/jquery.js"></script>
|
||||
<script src="jquery-ui/jquery-ui.js"></script>
|
||||
<script src="jquery-ui/jquery-ui.js"></script>
|
||||
<script src="flot/jquery.flot.js"></script>
|
||||
<script src="flot/jquery.flot.time.js"></script>
|
||||
<script src="msg.js"></script>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="header">
|
||||
<img class="logo" alt="EONERC" src="eonerc_logo.png" />
|
||||
<img class="logo" alt="EONERC" src="logo.svg" />
|
||||
<h1>VILALSnode / WebSocket Mockup</h1>
|
||||
</div>
|
||||
<div id="container">
|
||||
|
@ -29,7 +29,7 @@
|
|||
|
||||
<div class="controls">
|
||||
<dl>
|
||||
<dt><label for="buttons">Buttons</label></dt>
|
||||
<dt><label>Buttons</label></dt>
|
||||
<dd>
|
||||
<button>1</button>
|
||||
<button>2</button>
|
||||
|
@ -49,10 +49,22 @@
|
|||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="plot-controls">
|
||||
<dl>
|
||||
<dt><label for="timespan">Plot timespan</label></dt>
|
||||
<dd><div id="timespan"></div></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="connection">
|
||||
<span>Status:</span> <span id="connectionStatus"></span>
|
||||
<button id="pause" onclick="wsDisconnect()">Pause</button>
|
||||
<button id="pause" onclick="wsConnect()">Play</button>
|
||||
<dl>
|
||||
<dt><label>Status</label></dt>
|
||||
<dd>
|
||||
<button id="pause">Pause</button>
|
||||
<button id="play">Play</button>
|
||||
<span id="connectionStatus"></span>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
|
|
1
contrib/websocket/logo.svg
Symbolic link
1
contrib/websocket/logo.svg
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../doc/pictures/acs_eonerc_logo.svg
|
|
@ -12,18 +12,10 @@
|
|||
* @{
|
||||
**********************************************************************************/
|
||||
|
||||
/* Class for parsing and printing a message / sample */
|
||||
function Msg(members) {
|
||||
for(var k in members)
|
||||
this[k] = members[k];
|
||||
}
|
||||
|
||||
/* Some constants for the binary protocol */
|
||||
Msg.prototype.VERSION = 1;
|
||||
|
||||
Msg.prototype.TYPE_DATA = 0; /**< Message contains float values */
|
||||
Msg.prototype.TYPE_START = 1; /**< Message marks the beginning of a new simulation case */
|
||||
Msg.prototype.TYPE_STOP = 2; /**< Message marks the end of a simulation case */
|
||||
|
||||
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 */
|
||||
|
@ -33,17 +25,29 @@ Msg.prototype.OFFSET_ENDIAN = 1;
|
|||
Msg.prototype.OFFSET_TYPE = 2;
|
||||
Msg.prototype.OFFSET_VERSION = 4;
|
||||
|
||||
Msg.prototype.values = function() {
|
||||
return this.values * 4 + 16;
|
||||
}
|
||||
|
||||
Msg.prototype.toArrayBuffer = function() {
|
||||
var blob = new ArrayBuffer(this.values());
|
||||
/* Class for parsing and printing a message */
|
||||
function Msg(c, d)
|
||||
{
|
||||
this.sequence = c.sequence || 0;
|
||||
this.length = c.length || 0;
|
||||
this.endian = c.endian || Msg.ENDIAN_LITTLE;
|
||||
this.version = c.version || Msg.VERSION;
|
||||
this.type = c.type || Msg.TYPE_DATA;
|
||||
this.timestamp = c.timestamp || Date.now();
|
||||
|
||||
return blob;
|
||||
if (Array.isArray(d)) {
|
||||
this.length = d.length;
|
||||
this.data = d
|
||||
}
|
||||
}
|
||||
|
||||
Msg.fromArrayBuffer = function(data) {
|
||||
Msg.bytes = function(len)
|
||||
{
|
||||
return len * 4 + 16;
|
||||
}
|
||||
|
||||
Msg.fromArrayBuffer = function(data)
|
||||
{
|
||||
var bits = data.getUint8(0);
|
||||
var endian = (bits >> Msg.OFFSET_ENDIAN) & 0x1 ? 0 : 1;
|
||||
|
||||
|
@ -51,14 +55,14 @@ Msg.fromArrayBuffer = function(data) {
|
|||
endian: (bits >> Msg.OFFSET_ENDIAN) & 0x1,
|
||||
version: (bits >> Msg.OFFSET_VERSION) & 0xF,
|
||||
type: (bits >> Msg.OFFSET_TYPE) & 0x3,
|
||||
values: data.getUint16(0x02, endian),
|
||||
length: data.getUint16(0x02, endian),
|
||||
sequence: data.getUint32(0x04, endian),
|
||||
timestamp: data.getUint32(0x08, endian) * 1e3 +
|
||||
data.getUint32(0x0C, endian) * 1e-6,
|
||||
});
|
||||
|
||||
msg.blob = new DataView( data.buffer, data.byteOffset + 0x00, (msg.values + 4) * 4);
|
||||
msg.data = new Float32Array(data.buffer, data.byteOffset + 0x10, msg.values);
|
||||
msg.blob = new DataView( data.buffer, data.byteOffset + 0x00, Msg.bytes(msg.length));
|
||||
msg.data = new Float32Array(data.buffer, data.byteOffset + 0x10, msg.length);
|
||||
|
||||
if (msg.endian != host_endianess()) {
|
||||
console.warn("Message is not given in host endianess!");
|
||||
|
@ -71,7 +75,8 @@ Msg.fromArrayBuffer = function(data) {
|
|||
return msg;
|
||||
}
|
||||
|
||||
Msg.fromArrayBufferVector = function(blob) {
|
||||
Msg.fromArrayBufferVector = function(blob)
|
||||
{
|
||||
/* some local variables for parsing */
|
||||
var offset = 0;
|
||||
var msgs = [];
|
||||
|
@ -90,8 +95,34 @@ Msg.fromArrayBufferVector = function(blob) {
|
|||
return msgs;
|
||||
}
|
||||
|
||||
Msg.prototype.toArrayBuffer = function()
|
||||
{
|
||||
buffer = new ArrayBuffer(Msg.bytes(this.length))
|
||||
view = new DataView(buffer);
|
||||
|
||||
var bits = 0;
|
||||
bits |= (this.endian & 0x1) << Msg.OFFSET_ENDIAN;
|
||||
bits |= (this.version & 0xF) << Msg.OFFSET_VERSION;
|
||||
bits |= (this.type & 0x3) << Msg.OFFSET_TYPE;
|
||||
|
||||
var sec = Math.floor(this.timestamp / 1e3);
|
||||
var nsec = (this.timestamp - sec * 1e3) * 1e3;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** @todo parsing of big endian messages not yet supported */
|
||||
function swap16(val) {
|
||||
function swap16(val)
|
||||
{
|
||||
return ((val & 0xFF) << 8)
|
||||
| ((val >> 8) & 0xFF);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ body {
|
|||
padding: 20px;
|
||||
}
|
||||
|
||||
#slider {
|
||||
.ui-slider {
|
||||
width: 300px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -64,4 +64,17 @@ li.active {
|
|||
|
||||
.on {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
/* Definition lists */
|
||||
dt {
|
||||
float: left;
|
||||
clear: left;
|
||||
width: 8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 0.7em;
|
||||
margin-left: 0px;
|
||||
}
|
179
doc/pictures/acs_eonerc_logo.svg
Normal file
179
doc/pictures/acs_eonerc_logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 29 KiB |
Loading…
Add table
Reference in a new issue