From b9d40a861e314ee0104a4af73fa0472886556169 Mon Sep 17 00:00:00 2001 From: Markus Grigull Date: Tue, 26 Jul 2016 20:40:33 +0200 Subject: [PATCH] Add running-simulation service Simulation-model index now shows correct simulator data if the selected simulation is running. running-simulation service can be used to get the running simulation anywhere in the app. --- app/controllers/simulation-model/index.js | 43 ++++++++++++++++ app/mixins/websocket-live-stream-mixin.js | 51 +++++++++++++++---- app/services/running-simulation.js | 41 +++++++++++++++ app/templates/simulation-model/index.hbs | 19 +++++-- app/templates/simulations.hbs | 4 ++ .../unit/services/running-simulation-test.js | 12 +++++ 6 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 app/services/running-simulation.js create mode 100644 tests/unit/services/running-simulation-test.js diff --git a/app/controllers/simulation-model/index.js b/app/controllers/simulation-model/index.js index 55ff9aa..74b0a77 100644 --- a/app/controllers/simulation-model/index.js +++ b/app/controllers/simulation-model/index.js @@ -1,4 +1,47 @@ +/** + * File: index.js + * Author: Markus Grigull + * Date: 20.07.2016 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + import Ember from 'ember'; export default Ember.Controller.extend({ + values: function() { + return this.get('simulationData.values'); + }.property('simulationData.values.@each'), + + _getData: function() { + if (this.get('model.simulation.running') == true) { + var simulator = this.get('model.simulator'); + if (simulator == null) { + return; + } + + var data = this.store.peekRecord('simulation-data', simulator); + this.set('simulationData', data); + + // load model again if simulation data is null + // this prevents from simulation data not being loaded when the controller + // is loaded before the websocket connects + if (data === null) { + Ember.run.later(this, function() { + // trigger _getData + this.notifyPropertyChange('model'); + }, 1000); + } + } else { + // clear simulation data + this.set('simulationData', null); + + // check again if simulation is running now + Ember.run.later(this, function() { + // trigger _getData + this.notifyPropertyChange('model'); + }, 1000); + } + }.observes('model').on('init') }); diff --git a/app/mixins/websocket-live-stream-mixin.js b/app/mixins/websocket-live-stream-mixin.js index eaaf392..bbf6ecf 100644 --- a/app/mixins/websocket-live-stream-mixin.js +++ b/app/mixins/websocket-live-stream-mixin.js @@ -1,25 +1,56 @@ +/** + * File: websocket-live-stream-mixin.js + * Author: Markus Grigull + * Date: 21.07.2016 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + import Ember from 'ember'; import ENV from '../config/environment'; +const { service } = Ember.inject; + export default Ember.Mixin.create({ host: 'ws://' + ENV.APP.LIVE_HOST, namespace: '', + runningSimulation: service('running-simulation'), + + socket: null, init() { this._super(...arguments); - // create socket - var socket = new WebSocket(this.host + this.namespace); - socket.binaryType = 'arraybuffer'; - - // register event callbacks - var self = this; - socket.onopen = function(event) { self.onopen.apply(self, [event]); }; - socket.onclose = function(event) { self.onclose.apply(self, [event]); }; - socket.onmessage = function(event) { self.onmessage.apply(self, [event]); }; - socket.onerror = function(event) { self.onerror.apply(self, [event]); }; + // start simulation service + this.get('runningSimulation').loadRunningSimulation(); }, + _runningSimulationChanged: function() { + // called each time running simulation did change + var simulation = this.get('runningSimulation.simulation'); + if (simulation !== null) { + if (this.socket === null) { + // create new socket connection + this.socket = new WebSocket(this.host + this.namespace); + this.socket.binaryType = 'arraybuffer'; + + // register callbacks + var self = this; + this.socket.onopen = function(event) { self.onopen.apply(self, [event]); }; + this.socket.onclose = function(event) { self.onclose.apply(self, [event]); }; + this.socket.onmessage = function(event) { self.onmessage.apply(self, [event]); }; + this.socket.onerror = function(event) { self.onerror.apply(self, [event]); }; + } + } else { + // stop stream if still opened + if (this.socket !== null) { + this.socket.close(); + this.socket = null; + } + } + }.observes('runningSimulation.simulation'), + onopen(event) { Ember.debug('websocket opened'); }, diff --git a/app/services/running-simulation.js b/app/services/running-simulation.js new file mode 100644 index 0000000..ca8ff7b --- /dev/null +++ b/app/services/running-simulation.js @@ -0,0 +1,41 @@ +/** + * File: running-simulation.js + * Author: Markus Grigull + * Date: 26.07.2016 + * Copyright: 2016, Institute for Automation of Complex Power Systems, EONERC + * This file is part of VILLASweb. All Rights Reserved. Proprietary and confidential. + * Unauthorized copying of this file, via any medium is strictly prohibited. + **********************************************************************************/ + +import Ember from 'ember'; + +const { + inject: { service } +} = Ember; + +export default Ember.Service.extend({ + session: service('session'), + store: service(), + + loadRunningSimulation: function() { + var self = this; + + // check every second for running simulation + setInterval(function() { + // check if running simulation did changed + self.get('store').findAll('simulation').then(function(simulations) { + var newSimulation = null; + + simulations.forEach(function(simulation) { + if (simulation.get('running') == true) { + newSimulation = simulation; + } + }); + + if (newSimulation != self.get('simulation')) { + self.set('simulation', newSimulation); + } + }); + }, 1000); + } +}); diff --git a/app/templates/simulation-model/index.hbs b/app/templates/simulation-model/index.hbs index 2c69e6f..d993484 100644 --- a/app/templates/simulation-model/index.hbs +++ b/app/templates/simulation-model/index.hbs @@ -1,9 +1,18 @@

{{model.name}}

- Running: {{#if model.running}} - true - {{else}} - false - {{/if}} + Running: {{model.simulation.running}}

+ +

+ Simulator: {{model.simulator}} +

+ +

+ Data: +

+ +{{#each values as |value|}} + {{value}} +
+{{/each}} diff --git a/app/templates/simulations.hbs b/app/templates/simulations.hbs index cac2d48..40fa4a6 100644 --- a/app/templates/simulations.hbs +++ b/app/templates/simulations.hbs @@ -4,6 +4,7 @@ + {{#each model as |simulation|}} @@ -11,6 +12,9 @@ +
NameRunning
{{#link-to "simulation.index" simulation.id}}{{simulation.name}}{{/link-to}} + {{simulation.running}} +
{{#link-to "simulation.edit" simulation.id}}Edit{{/link-to}} diff --git a/tests/unit/services/running-simulation-test.js b/tests/unit/services/running-simulation-test.js new file mode 100644 index 0000000..f74cde8 --- /dev/null +++ b/tests/unit/services/running-simulation-test.js @@ -0,0 +1,12 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:running-simulation', 'Unit | Service | running simulation', { + // Specify the other units that are required for this test. + // needs: ['service:foo'] +}); + +// Replace this with your real tests. +test('it exists', function(assert) { + let service = this.subject(); + assert.ok(service); +});