diff --git a/src/containers/app.js b/src/containers/app.js index adc5f05..70bbe67 100644 --- a/src/containers/app.js +++ b/src/containers/app.js @@ -27,7 +27,6 @@ import NotificationSystem from 'react-notification-system'; import AppDispatcher from '../app-dispatcher'; import SimulationStore from '../stores/simulation-store'; -//import SimulatorStore from '../stores/simulator-store'; import NodeStore from '../stores/node-store'; import UserStore from '../stores/user-store'; import NotificationsDataManager from '../data-managers/notifications-data-manager'; @@ -81,6 +80,7 @@ class App extends Component { return { nodes: NodeStore.getState(), + simulations: SimulationStore.getState(), currentRole: currentUser? currentUser.role : '', token: UserStore.getState().token/*, @@ -127,53 +127,46 @@ class App extends Component { return; } - // open connection to each required simulator - const requiredSimulators = this.requiredSimulatorsBySimulations(); + // open connection to each node + /*const requiredNodes = this.requiredNodesBySimulations(); - requiredSimulators.forEach(simulator => { - this.connectSimulator(nextState, simulator); - }); + requiredNodes.forEach(node => { + AppDispatcher.dispatch({ + type: 'simulatorData/open', + identifier: simulator._id, + endpoint: node.endpoint, + signals: data.signals + }); + });*/ } - requiredSimulatorsBySimulations() { - return []; + /*requiredNodesBySimulations() { + var nodes = {}; - /*var simulators = []; - - this.state.simulations.forEach((simulation) => { - simulation.models.forEach((simulationModel) => { - // add simulator to list if not already part of - const index = simulators.findIndex((element) => { - return element.simulator === simulationModel.simulator; + this.state.simulations.forEach(simulation => { + simulation.models.forEach(model => { + // get ID for node + var node = this.state.nodes.find(element => { + return element.name === model.simulator.node; }); - if (index === -1) { - simulators.push({ simulator: simulationModel.simulator, signals: simulationModel.length }); - } else { - if (simulators[index].length < simulationModel.length) { - simulators[index].length = simulationModel.length; + // add empty node if not existing + if (node !== undefined) { + if (nodes[node._id] == null) { + nodes[node._id] = { simulators: [] } } + + // get simulator id + var simulator = node.simulators.find(simulator => { + return simulator.name === model.simulator.simulator; + }); + + nodes[node._id].simulators.push({ id: simulator.id, signals: model.length }); } }); }); - return simulators;*/ - } - - /*connectSimulator(state, data) { - // get simulator object - const simulator = state.runningSimulators.find(element => { - return element._id === data.simulator; - }); - - if (simulator != null) { - AppDispatcher.dispatch({ - type: 'simulatorData/open', - identifier: simulator._id, - endpoint: simulator.endpoint, - signals: data.signals - }); - } + return nodes; }*/ render() { diff --git a/src/data-managers/nodes-data-manager.js b/src/data-managers/nodes-data-manager.js index af68fc1..12e4014 100644 --- a/src/data-managers/nodes-data-manager.js +++ b/src/data-managers/nodes-data-manager.js @@ -29,7 +29,7 @@ class NodesDataManager extends RestDataManager { } getSimulators(node) { - /*RestAPI.post('http://' + node.endpoint + '/api/v1', { + RestAPI.post('http://' + node.endpoint + '/api/v1', { action: 'nodes', id: node._id }).then(response => { @@ -51,12 +51,18 @@ class NodesDataManager extends RestDataManager { type: 'nodes/edited', data: node }); + + AppDispatcher.dispatch({ + type: 'simulatorData/open', + node: node, + endpoint: node.endpoint, + }); }).catch(error => { AppDispatcher.dispatch({ type: 'nodes/edit-error', error: error }); - });*/ + }); } } diff --git a/src/data-managers/simulator-data-data-manager.js b/src/data-managers/simulator-data-data-manager.js index 22f443b..666ea5e 100644 --- a/src/data-managers/simulator-data-data-manager.js +++ b/src/data-managers/simulator-data-data-manager.js @@ -27,21 +27,21 @@ class SimulatorDataDataManager { this._sockets = {}; } - open(endpoint, identifier, signals) { + open(endpoint, node) { // pass signals to onOpen callback - if (this._sockets[identifier] != null) { - if (this._sockets[identifier].url !== WebsocketAPI.getURL(endpoint)) { + if (this._sockets[node._id] != null) { + if (this._sockets[node._id].url !== WebsocketAPI.getURL(endpoint)) { // replace connection, since endpoint changed this._sockets.close(); - this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) }); + this._sockets[node._id] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, node), onClose: (event) => this.onClose(event, node), onMessage: (event) => this.onMessage(event, node) }); } } else { // set flag if a socket to this simulator was already create before - if (this._sockets[identifier] === null) { - this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals, false), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) }); + if (this._sockets[node._id] === null) { + this._sockets[node._id] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, node, false), onClose: (event) => this.onClose(event, node), onMessage: (event) => this.onMessage(event, node) }); } else { - this._sockets[identifier] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, identifier, signals, true), onClose: (event) => this.onClose(event, identifier), onMessage: (event) => this.onMessage(event, identifier) }); + this._sockets[node._id] = WebsocketAPI.addSocket(endpoint, { onOpen: (event) => this.onOpen(event, node, true), onClose: (event) => this.onClose(event, node), onMessage: (event) => this.onMessage(event, node) }); } } } @@ -56,33 +56,32 @@ class SimulatorDataDataManager { } } - onOpen(event, identifier, signals, firstOpen) { + onOpen(event, node, firstOpen) { AppDispatcher.dispatch({ type: 'simulatorData/opened', - identifier: identifier, - signals: signals, + node: node, firstOpen: firstOpen }); } - onClose(event, identifier) { + onClose(event, node) { AppDispatcher.dispatch({ type: 'simulatorData/closed', - identifier: identifier, + node: node, notification: (event.code !== 4000) }); // remove from list, keep null reference for flag detection - delete this._sockets[identifier]; + delete this._sockets[node._id]; } - onMessage(event, identifier) { + onMessage(event, node) { var message = this.bufferToMessage(event.data); AppDispatcher.dispatch({ type: 'simulatorData/data-changed', data: message, - identifier: identifier + node: node }); } @@ -95,6 +94,7 @@ class SimulatorDataDataManager { var bits = data.getUint8(0); var length = data.getUint16(0x02, 1); + var id = data.getUint8(1); var values = new Float32Array(data.buffer, data.byteOffset + 0x10, length); @@ -104,7 +104,8 @@ class SimulatorDataDataManager { length: length, sequence: data.getUint32(0x04, 1), timestamp: data.getUint32(0x08, 1) * 1e3 + data.getUint32(0x0C, 1) * 1e-6, - values: values + values: values, + id: id }; } } diff --git a/src/stores/node-store.js b/src/stores/node-store.js index d7d6112..aad1df6 100644 --- a/src/stores/node-store.js +++ b/src/stores/node-store.js @@ -30,6 +30,7 @@ class NodeStore extends ArrayStore { reduce(state, action) { switch(action.type) { case 'nodes/loaded': + // get simulator IDs if (Array.isArray(action.data)) { action.data.forEach(node => { NodesDataManager.getSimulators(node); diff --git a/src/stores/simulator-data-store.js b/src/stores/simulator-data-store.js index d52ac1d..457768c 100644 --- a/src/stores/simulator-data-store.js +++ b/src/stores/simulator-data-store.js @@ -40,48 +40,58 @@ class SimulationDataStore extends ReduceStore { switch (action.type) { case 'simulatorData/open': - SimulatorDataDataManager.open(action.endpoint, action.identifier, action.signals); + SimulatorDataDataManager.open(action.endpoint, action.node); return state; case 'simulatorData/opened': // create entry for simulator - state[action.identifier] = { signals: action.signals, values: [], sequence: null, timestamp: null }; + /*state[action.identifier] = { signals: action.signals, values: [], sequence: null, timestamp: null }; for (i = 0; i < action.signals; i++) { state[action.identifier].values.push([]); - } + }*/ + + state[action.node._id] = {}; + + action.node.simulators.forEach(simulator => { + state[action.node._id][simulator.id] = { sequence: -1, values: [] }; + }); return state; case 'simulatorData/data-changed': // only add data, if newer than current - if (state[action.identifier].sequence < action.data.sequence) { + if (state[action.node._id][action.data.id].sequence < action.data.sequence) { // add data to simulator - for (i = 0; i < state[action.identifier].signals; i++) { - state[action.identifier].values[i].push({ x: action.data.timestamp, y: action.data.values[i] }); + for (i = 0; i < action.data.length; i++) { + while (state[action.node._id][action.data.id].values.length < i + 1) { + state[action.node._id][action.data.id].values.push([]); + } + + state[action.node._id][action.data.id].values[i].push({ x: action.data.timestamp, y: action.data.values[i] }); // erase old values - if (state[action.identifier].values[i].length > MAX_VALUES) { - const pos = state[action.identifier].values[i].length - MAX_VALUES; - state[action.identifier].values[i].splice(0, pos); + if (state[action.node._id][action.data.id].values[i].length > MAX_VALUES) { + const pos = state[action.node._id][action.data.id].values[i].length - MAX_VALUES; + state[action.node._id][action.data.id].values[i].splice(0, pos); } } // update metadata - state[action.identifier].timestamp = action.data.timestamp; - state[action.identifier].sequence = action.data.sequence; + state[action.node._id][action.data.id].timestamp = action.data.timestamp; + state[action.node._id][action.data.id].sequence = action.data.sequence; // explicit call to prevent array copy this.__emitChange(); } else { - console.log('same sequence ' + state[action.identifier].sequence + ' ' + action.data.sequence); + console.log('same sequence ' + state[action.node._id][action.data.id].sequence + ' ' + action.data.sequence); } return state; case 'simulatorData/closed': // close and delete socket - if (state[action.identifier] != null) { + if (state[action.node] != null) { // delete data //delete state[action.identifier]; //state[action.identifier] = null;