mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Move websocket live stream into mixin
Add simulator to websocket message Add history to simulator-data
This commit is contained in:
parent
4a9563f603
commit
5b09486d3c
11 changed files with 134 additions and 164 deletions
|
@ -1,108 +0,0 @@
|
|||
/**
|
||||
* File: simulation-data.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* 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';
|
||||
import DS from 'ember-data';
|
||||
import ENV from '../config/environment';
|
||||
|
||||
export default DS.Adapter.extend({
|
||||
host: 'ws://' + ENV.APP.LIVE_HOST,
|
||||
namespace: '',
|
||||
|
||||
socket: null,
|
||||
|
||||
findRecord(store, type, id, snapshot) {
|
||||
this._init();
|
||||
|
||||
return new Ember.RSVP.Promise(function(resolve, reject) {
|
||||
//reject(new Error('no record'));
|
||||
reject();
|
||||
});
|
||||
},
|
||||
|
||||
_init() {
|
||||
if (this.socket === null) {
|
||||
// create new websocket
|
||||
this.socket = new WebSocket(this.host + this.namespace);
|
||||
this.socket.binaryType = 'arraybuffer';
|
||||
|
||||
// register event callbacks
|
||||
var self = this;
|
||||
this.socket.onopen = function(event) {
|
||||
self.open.apply(self, [event]);
|
||||
};
|
||||
|
||||
this.socket.onmessage = function(event) {
|
||||
self.message.apply(self, [event]);
|
||||
};
|
||||
|
||||
this.socket.onerror = function(event) {
|
||||
self.error.apply(self, [event]);
|
||||
};
|
||||
|
||||
this.socket.onclose = function(event) {
|
||||
self.close.apply(self, [event]);
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
open(event) {
|
||||
Ember.debug('websocket opened');
|
||||
},
|
||||
|
||||
close(event) {
|
||||
Ember.debug('websocket closed: ' + event.code);
|
||||
},
|
||||
|
||||
message(event) {
|
||||
// read the message into JSON
|
||||
var message = this._messageToJSON(event.data);
|
||||
var id = 0;
|
||||
|
||||
var simulationData = this.store.peekRecord('simulation-data', id);
|
||||
if (simulationData != null) {
|
||||
simulationData.set('sequence', message.sequence);
|
||||
simulationData.set('values', message.values);
|
||||
} else {
|
||||
this.store.createRecord('simulation-data', {
|
||||
sequence: message.sequence,
|
||||
values: message.values,
|
||||
id: id
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
error(err) {
|
||||
Ember.debug('websocket error');
|
||||
},
|
||||
|
||||
_messageToJSON(blob) {
|
||||
var data = new DataView(blob);
|
||||
|
||||
let OFFSET_ENDIAN = 1;
|
||||
let OFFSET_TYPE = 2;
|
||||
let OFFSET_VERSION = 4;
|
||||
|
||||
var bits = data.getUint8(0);
|
||||
var endian = (bits >> OFFSET_ENDIAN) & 0x1 ? 0 : 1;
|
||||
var length = data.getUint16(0x02, endian);
|
||||
|
||||
var values = new Float32Array(data.buffer, data.byteOffset + 0x10, length);
|
||||
|
||||
return {
|
||||
endian: endian,
|
||||
version: (bits >> OFFSET_VERSION) & 0xF,
|
||||
type: (bits >> OFFSET_TYPE) & 0x3,
|
||||
length: length,
|
||||
sequence: data.getUint32(0x04, endian),
|
||||
timestamp: data.getUint32(0x08, endian) * 1e3 + data.getUint32(0x0C, endian) * 1e-6,
|
||||
values: values
|
||||
};
|
||||
}
|
||||
});
|
|
@ -1,4 +1,21 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
sequence: function() {
|
||||
return this.get('model.sequence');
|
||||
}.property('model.sequence'),
|
||||
|
||||
values: function() {
|
||||
return this.get('model.values');
|
||||
}.property('model.values.@each'),
|
||||
|
||||
_updateModel: function() {
|
||||
if (this.get('model') === null) {
|
||||
Ember.run.later(this, function() {
|
||||
var simulationData = this.store.peekRecord('simulation-data', 1);
|
||||
this.set('model', simulationData);
|
||||
this.notifyPropertyChange('model');
|
||||
}, 500);
|
||||
}
|
||||
}.observes('model').on('init')
|
||||
});
|
||||
|
|
77
app/mixins/websocket-live-stream-mixin.js
Normal file
77
app/mixins/websocket-live-stream-mixin.js
Normal file
|
@ -0,0 +1,77 @@
|
|||
import Ember from 'ember';
|
||||
import ENV from '../config/environment';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
host: 'ws://' + ENV.APP.LIVE_HOST,
|
||||
namespace: '',
|
||||
|
||||
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]); };
|
||||
},
|
||||
|
||||
onopen(event) {
|
||||
Ember.debug('websocket opened');
|
||||
},
|
||||
|
||||
onclose(event) {
|
||||
Ember.debug('websocket closed: ' + event.code);
|
||||
},
|
||||
|
||||
onmessage(event) {
|
||||
// read the message into JSON
|
||||
var message = this._messageToJSON(event.data);
|
||||
|
||||
var simulationData = this.store.peekRecord('simulation-data', message.simulator);
|
||||
if (simulationData != null) {
|
||||
simulationData.set('sequence', message.sequence);
|
||||
simulationData.set('values', message.values);
|
||||
} else {
|
||||
this.store.createRecord('simulation-data', {
|
||||
sequence: message.sequence,
|
||||
values: message.values,
|
||||
id: message.simulator
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onerror(event) {
|
||||
Ember.debug('websocket error');
|
||||
},
|
||||
|
||||
_messageToJSON(blob) {
|
||||
var data = new DataView(blob);
|
||||
|
||||
let OFFSET_ENDIAN = 1;
|
||||
let OFFSET_TYPE = 2;
|
||||
let OFFSET_VERSION = 4;
|
||||
|
||||
var bits = data.getUint8(0);
|
||||
var simulator = data.getUint8(0x01);
|
||||
var endian = (bits >> OFFSET_ENDIAN) & 0x1 ? 0 : 1;
|
||||
var length = data.getUint16(0x02, endian);
|
||||
|
||||
var values = new Float32Array(data.buffer, data.byteOffset + 0x10, length);
|
||||
|
||||
return {
|
||||
endian: endian,
|
||||
version: (bits >> OFFSET_VERSION) & 0xF,
|
||||
type: (bits >> OFFSET_TYPE) & 0x3,
|
||||
length: length,
|
||||
sequence: data.getUint32(0x04, endian),
|
||||
timestamp: data.getUint32(0x08, endian) * 1e3 + data.getUint32(0x0C, endian) * 1e-6,
|
||||
values: values,
|
||||
simulator: simulator
|
||||
};
|
||||
}
|
||||
});
|
|
@ -7,12 +7,26 @@
|
|||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
**********************************************************************************/
|
||||
|
||||
import Ember from 'ember';
|
||||
import Model from 'ember-data/model';
|
||||
import attr from 'ember-data/attr';
|
||||
// import { belongsTo, hasMany } from 'ember-data/relationships';
|
||||
|
||||
export default Model.extend({
|
||||
simulator: attr('number'),
|
||||
simulator: Ember.computed.alias('id'),
|
||||
sequence: attr('number'),
|
||||
values: attr('array')
|
||||
values: attr('array'),
|
||||
|
||||
historyValues() {
|
||||
return this._history;
|
||||
},
|
||||
|
||||
_history: [],
|
||||
|
||||
_updateHistory: function() {
|
||||
this._history.unshift(this.get('values'));
|
||||
while (this._history.length > 500) {
|
||||
this._history.shift();
|
||||
}
|
||||
}.observes('values')
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
import Ember from 'ember';
|
||||
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
|
||||
import WebsocketLiveStreamMixin from '../mixins/websocket-live-stream-mixin';
|
||||
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, {
|
||||
export default Ember.Route.extend(AuthenticatedRouteMixin, WebsocketLiveStreamMixin, {
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
/*model() {
|
||||
return this.store.findRecord('simulation-data', 0);
|
||||
}*/
|
||||
model() {
|
||||
return this.store.peekRecord('simulation-data', 1);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* File: simulation-data.js
|
||||
* Author: Markus Grigull <mgrigull@eonerc.rwth-aachen.de>
|
||||
* 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';
|
||||
import DS from 'ember-data';
|
||||
|
||||
export default DS.Serializer.extend({
|
||||
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
|
||||
console.log('normalizeResponse');
|
||||
return {};
|
||||
},
|
||||
|
||||
serialize(record, options) {
|
||||
console.log('serialize');
|
||||
return null;
|
||||
}
|
||||
});
|
|
@ -1 +1,8 @@
|
|||
{{sequence}}
|
||||
|
||||
<br />
|
||||
|
||||
{{#each values as |value|}}
|
||||
{{value}}
|
||||
<br />
|
||||
{{/each}}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('adapter:simulation-data', 'Unit | Adapter | simulation data', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['serializer:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let adapter = this.subject();
|
||||
assert.ok(adapter);
|
||||
});
|
12
tests/unit/mixins/websocket-live-stream-mixin-test.js
Normal file
12
tests/unit/mixins/websocket-live-stream-mixin-test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import Ember from 'ember';
|
||||
import WebsocketLiveStreamMixinMixin from 'villasweb-frontend/mixins/websocket-live-stream-mixin';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Mixin | websocket live stream mixin');
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it works', function(assert) {
|
||||
let WebsocketLiveStreamMixinObject = Ember.Object.extend(WebsocketLiveStreamMixinMixin);
|
||||
let subject = WebsocketLiveStreamMixinObject.create();
|
||||
assert.ok(subject);
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
import { moduleForModel, test } from 'ember-qunit';
|
||||
|
||||
moduleForModel('simulation-data', 'Unit | Serializer | simulation data', {
|
||||
// Specify the other units that are required for this test.
|
||||
needs: ['serializer:simulation-data']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it serializes records', function(assert) {
|
||||
let record = this.subject();
|
||||
|
||||
let serializedRecord = record.serialize();
|
||||
|
||||
assert.ok(serializedRecord);
|
||||
});
|
Loading…
Add table
Reference in a new issue