mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-30 00:00:13 +01:00
Add live data flow from visualization to plots
Fix live-data mixin
This commit is contained in:
parent
f2d494a1b0
commit
59c9438ce1
10 changed files with 140 additions and 90 deletions
|
@ -19,8 +19,9 @@ export default Ember.Component.extend(Resizable, Draggable, {
|
||||||
plot: null,
|
plot: null,
|
||||||
editing: false,
|
editing: false,
|
||||||
grid: false,
|
grid: false,
|
||||||
|
data: null,
|
||||||
|
|
||||||
simulator: 0,
|
simulator: 0
|
||||||
|
|
||||||
disabled_resize: false,
|
disabled_resize: false,
|
||||||
autoHide_resize: false,
|
autoHide_resize: false,
|
||||||
|
|
|
@ -17,6 +17,7 @@ export default Ember.Component.extend({
|
||||||
plots: null,
|
plots: null,
|
||||||
editing: false,
|
editing: false,
|
||||||
grid: true,
|
grid: true,
|
||||||
|
data: null,
|
||||||
|
|
||||||
style: function() {
|
style: function() {
|
||||||
var height = this._calculateHeight();
|
var height = this._calculateHeight();
|
||||||
|
@ -27,6 +28,10 @@ export default Ember.Component.extend({
|
||||||
return Ember.String.htmlSafe('height: ' + height + 'px;');
|
return Ember.String.htmlSafe('height: ' + height + 'px;');
|
||||||
}.property('plots.@each.height', 'plots.@each.y'),
|
}.property('plots.@each.height', 'plots.@each.y'),
|
||||||
|
|
||||||
|
_value: function() {
|
||||||
|
console.log(this.get('data'));
|
||||||
|
}.property('data.2.values.@each'),
|
||||||
|
|
||||||
_calculateHeight() {
|
_calculateHeight() {
|
||||||
var maxHeight = 0;
|
var maxHeight = 0;
|
||||||
var plots = this.get('plots');
|
var plots = this.get('plots');
|
||||||
|
|
|
@ -13,5 +13,21 @@ export default PlotAbstract.extend({
|
||||||
classNames: [ 'plotValue' ],
|
classNames: [ 'plotValue' ],
|
||||||
|
|
||||||
minWidth_resize: 50,
|
minWidth_resize: 50,
|
||||||
minHeight_resize: 20
|
minHeight_resize: 20,
|
||||||
|
|
||||||
|
simulator: 2,
|
||||||
|
signal: 1,
|
||||||
|
|
||||||
|
value: function() {
|
||||||
|
// get all values for the choosen simulator
|
||||||
|
let values = this.get('data.' + this.get('simulator') + '.values');
|
||||||
|
if (values) {
|
||||||
|
return values[this.get('signal')];
|
||||||
|
}
|
||||||
|
|
||||||
|
// values is null, try to reload later
|
||||||
|
Ember.run.later(this, function() {
|
||||||
|
this.notifyPropertyChange('data.' + this.get('simulator') + '.values');
|
||||||
|
}, 1000);
|
||||||
|
}.property('data.2.values')
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,4 +10,65 @@
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
|
data: {},
|
||||||
|
|
||||||
|
/*values: function() {
|
||||||
|
console.log('update');
|
||||||
|
return this.get('data');
|
||||||
|
}.property('data.2.values'),*/
|
||||||
|
|
||||||
|
_getData: function() {
|
||||||
|
// check if simulation is running
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
this.get('model.project').then((project) => {
|
||||||
|
project.get('simulation').then((simulation) => {
|
||||||
|
if (simulation.get('running')) {
|
||||||
|
// get all models to access data
|
||||||
|
simulation.get('models').then((simulationModels) => {
|
||||||
|
simulationModels.forEach(function(simulationModel) {
|
||||||
|
// get simulator
|
||||||
|
simulationModel.get('simulator').then((simulator) => {
|
||||||
|
let simulatorID = simulator.get('simulatorid');
|
||||||
|
if (simulatorID) {
|
||||||
|
// add simulation data to list
|
||||||
|
self._loadDataForSimulator(simulatorID);
|
||||||
|
} else {
|
||||||
|
Ember.debug('undefined simulator id');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// clear simulation data
|
||||||
|
this.set('data', {});
|
||||||
|
|
||||||
|
//Ember.debug('Simulation not running');
|
||||||
|
|
||||||
|
// check again if simulation is running
|
||||||
|
Ember.run.later(this, function() {
|
||||||
|
// trigger _getData observer
|
||||||
|
this.notifyPropertyChange('model');
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}.observes('model'),
|
||||||
|
|
||||||
|
_loadDataForSimulator(simulatorID) {
|
||||||
|
// get data by simulator id
|
||||||
|
let simulationData = this.store.peekRecord('simulation-data', simulatorID);
|
||||||
|
if (simulationData) {
|
||||||
|
// add data to list
|
||||||
|
this.get('data')[simulatorID] = simulationData;
|
||||||
|
|
||||||
|
// notify object for property changes
|
||||||
|
this.notifyPropertyChange('data.' + simulatorID + '.values');
|
||||||
|
} else {
|
||||||
|
// try to load data later
|
||||||
|
Ember.run.later(this, function() {
|
||||||
|
this._loadDataForSimulator(simulatorID);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default Ember.Mixin.create({
|
||||||
|
|
||||||
INTERVAL: 5000,
|
INTERVAL: 5000,
|
||||||
|
|
||||||
_sockets: [],
|
_sockets: {},
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
this._super();
|
this._super();
|
||||||
|
@ -36,79 +36,79 @@ export default Ember.Mixin.create({
|
||||||
_fetchRunningSimulations: function() {
|
_fetchRunningSimulations: function() {
|
||||||
// check if the user is logged in
|
// check if the user is logged in
|
||||||
if (this.get('sessionUser.user') != null) {
|
if (this.get('sessionUser.user') != null) {
|
||||||
// load simulators
|
// get all simulations to find all running ones
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.get('store').findAll('simulator').then(function() {
|
this.get('store').findAll('simulation').then(function(simulations) {
|
||||||
// get all simulations to find all running ones
|
simulations.forEach(function(simulation) {
|
||||||
self.get('store').findAll('simulation').then(function(simulations) {
|
// check if the simulation is running
|
||||||
simulations.forEach(function(simulation) {
|
if (simulation.get('running')) {
|
||||||
// check if the simulation is running
|
// get all models for this simulation
|
||||||
if (simulation.get('running')) {
|
simulation.get('models').then((models) => {
|
||||||
// get all models
|
models.forEach(function(simulationModel) {
|
||||||
simulation.get('models').forEach(function(model) {
|
self._addSocket(simulationModel);
|
||||||
self.get('store').findRecord('simulation-model', model.get('id')).then(function(m) {
|
|
||||||
self._addSocket(m);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_addSocket(simulationModel) {
|
_addSocket(simulationModel) {
|
||||||
// search for existing socket
|
// check if socket is already open
|
||||||
var length = this.get('_sockets').length;
|
let id = simulationModel.get('id');
|
||||||
|
if (this.get('_sockets')[id] !== undefined) {
|
||||||
for (var i = 0; i < length; i++) {
|
//Ember.debug('skip ' + simulationModel.get('name'));
|
||||||
if (this.get('_sockets')[i].id === simulationModel.get('id')) {
|
return;
|
||||||
// dont do anything
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add new socket
|
// get simulator endpoint
|
||||||
var socket = new WebSocket('ws://' + simulationModel.get('simulator.endpoint'));
|
simulationModel.get('simulator').then((simulator) => {
|
||||||
socket.binaryType = 'arraybuffer';
|
// get simulator endpoint
|
||||||
|
let endpoint = simulator.get('endpoint');
|
||||||
|
if (endpoint) {
|
||||||
|
// add new socket
|
||||||
|
let socket = new WebSocket('ws://' + endpoint);
|
||||||
|
socket.binaryType = 'arraybuffer';
|
||||||
|
|
||||||
// register callbacks
|
// register callbacks
|
||||||
var self = this;
|
let self = this;
|
||||||
|
|
||||||
socket.onopen = function(event) { self._onSocketOpen.apply(self, [event]); };
|
socket.onopen = function(event) { self._onSocketOpen.apply(self, [event]); };
|
||||||
socket.onclose = function(event) { self._onSocketClose.apply(self, [event]); };
|
socket.onclose = function(event) { self._onSocketClose.apply(self, [event]); };
|
||||||
socket.onmessage = function(event) { self._onSocketMessage.apply(self, [event]); };
|
socket.onmessage = function(event) { self._onSocketMessage.apply(self, [event]); };
|
||||||
socket.onerror = function(event) { self._onSocketError.apply(self, [event]); };
|
socket.onerror = function(event) { self._onSocketError.apply(self, [event]); };
|
||||||
|
|
||||||
this.get('_sockets').pushObject({ id: simulationModel.get('id'), socket: socket });
|
// add socket to list of known sockets
|
||||||
|
this.get('_sockets')[id] = socket;
|
||||||
|
|
||||||
console.log('Socket created for ' + simulationModel.get('name') + ': ws://' + simulationModel.get('simulator.endpoint'));
|
//Ember.debug('Socket created for ' + simulationModel.get('name') + ': ws://' + endpoint);
|
||||||
|
} else {
|
||||||
|
Ember.debug('Undefined endpoint for ' + simulationModel.get('name'));
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_removeSocket(socket) {
|
_removeSocket(socket) {
|
||||||
var length = this.get('_sockets').length;
|
// search through all sockets
|
||||||
var i = 0;
|
let sockets = this.get('_sockets');
|
||||||
|
|
||||||
while (i < length) {
|
for (let id in sockets) {
|
||||||
if (this.get('_sockets')[i].socket === socket) {
|
if (sockets[id] === socket) {
|
||||||
// remove object from array
|
// remove socket from list
|
||||||
this.get('_sockets').slice(i, 1);
|
delete sockets[id];
|
||||||
console.log('socket removed');
|
|
||||||
} else {
|
|
||||||
// increase index if no object was removed
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onSocketOpen(/* event */) {
|
_onSocketOpen(/* event */) {
|
||||||
Ember.debug('websocket opened');
|
//Ember.debug('websocket opened');
|
||||||
},
|
},
|
||||||
|
|
||||||
_onSocketClose(event) {
|
_onSocketClose(event) {
|
||||||
if (event.wasClean) {
|
if (event.wasClean) {
|
||||||
|
Ember.debug('websocket closed');
|
||||||
} else {
|
} else {
|
||||||
Ember.debug('websocket closed: ' + event.code);
|
Ember.debug('websocket closed: ' + event.code);
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ export default Ember.Mixin.create({
|
||||||
},
|
},
|
||||||
|
|
||||||
_messageToJSON(blob) {
|
_messageToJSON(blob) {
|
||||||
|
// parse incoming message into usable data
|
||||||
var data = new DataView(blob);
|
var data = new DataView(blob);
|
||||||
|
|
||||||
let OFFSET_ENDIAN = 1;
|
let OFFSET_ENDIAN = 1;
|
||||||
|
|
|
@ -12,9 +12,6 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout
|
||||||
|
|
||||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||||
model(params) {
|
model(params) {
|
||||||
return Ember.RSVP.hash({
|
return this.store.findRecord('visualization', params.visualizationid);
|
||||||
/*simulation: this.store.findRecord('simulation', params.simulationid),*/
|
|
||||||
visualization: this.store.findRecord('visualization', params.visualizationid)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{{#each plots as |plot|}}
|
{{#each plots as |plot|}}
|
||||||
{{component plot.type plot=plot editing=editing grid=grid}}
|
{{component plot.type plot=plot editing=editing grid=grid data=data}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -1,31 +1 @@
|
||||||
Value
|
Value: {{value}}
|
||||||
|
|
||||||
<div class="popover-content hidden">
|
|
||||||
<div class="plot-edit-container">
|
|
||||||
<form class="plot-edit-form" {{action 'savePlot' on='submit'}}>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<label for="simulator">Simulator</label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input id='simulator' type='number' value=plot.simulator min=1 max=255 width='60px'}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<label for="signal">Signal</label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{input id='signal' value=plot.signal}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<button type="submit">Save</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{{#link-to 'project.index' project.id}}Back to {{model.project.name}}{{/link-to}}
|
{{#link-to 'project.index' model.project.id}}Back to {{model.project.name}}{{/link-to}}
|
||||||
|
|
||||||
<h1>{{model.visualization.name}}</h1>
|
<h1>{{model.name}}</h1>
|
||||||
|
|
||||||
{{plot-container plots=model.visualization.plots}}
|
{{plot-container plots=model.plots data=data}}
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{{#link-to "visualization.edit" model.visualization.id}}Edit layout{{/link-to}}
|
{{#link-to "visualization.edit" model.id}}Edit layout{{/link-to}}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -14,8 +14,7 @@ module.exports = function(environment) {
|
||||||
},
|
},
|
||||||
|
|
||||||
APP: {
|
APP: {
|
||||||
API_HOST: 'localhost:3000',
|
API_HOST: 'localhost:3000'
|
||||||
LIVE_HOST: 'localhost:4000'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue