diff --git a/src/common/api/websocket-api.js b/src/common/api/websocket-api.js index 89a1ee6..1462f39 100644 --- a/src/common/api/websocket-api.js +++ b/src/common/api/websocket-api.js @@ -14,6 +14,8 @@ * You should have received a copy of the GNU General Public License * along with VILLASweb. If not, see . ******************************************************************************/ +import NotificationsDataManager from "../data-managers/notifications-data-manager"; +import AppDispatcher from '../app-dispatcher'; class WebsocketAPI { constructor(websocketurl, callbacks) { @@ -65,6 +67,10 @@ class WebsocketAPI { } onOpen = e => { + AppDispatcher.dispatch({ + type: 'websocket/connected', + data: this.websocketurl, + }); this.wasConnected = true; if ('onOpen' in this.callbacks) @@ -78,6 +84,16 @@ class WebsocketAPI { } else { if (this.wasConnected) { + AppDispatcher.dispatch({ + type: 'websocket/connection-error', + data: this.websocketurl, + }); + const IC_WEBSOCKET_CONNECTION_ERROR = { + title: 'Websocket connection warning', + message: "Connection to " + this.websocketurl + " dropped. Attempt reconnect in 1 sec", + level: 'warning' + }; + NotificationsDataManager.addNotification(IC_WEBSOCKET_CONNECTION_ERROR); console.log("Connection to " + this.websocketurl + " dropped. Attempt reconnect in 1 sec"); window.setTimeout(() => { this.reconnect(); }, 1000); } diff --git a/src/widget/websocket-store.js b/src/widget/websocket-store.js new file mode 100644 index 0000000..0665cf9 --- /dev/null +++ b/src/widget/websocket-store.js @@ -0,0 +1,59 @@ +/** + * This file is part of VILLASweb. + * + * VILLASweb is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VILLASweb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VILLASweb. If not, see . + ******************************************************************************/ + +import ArrayStore from '../common/array-store'; + +class WebsocketStore extends ArrayStore { + + updateSocketStatus(state, socket) { + let checkInclusion = false; + state.forEach((element) => { + if (element.url === socket.url) { + element.connected = socket.connected; + checkInclusion = true; + } + }) + if (!checkInclusion) { + state.push(socket); + } + this.__emitChange(); + + return state; + } + + reduce(state, action) { + let tempSocket = {}; + switch (action.type) { + + case 'websocket/connected': + tempSocket.url = action.data; + tempSocket.connected = true; + return this.updateSocketStatus(state, tempSocket); + + case 'websocket/connection-error': + tempSocket.url = action.data; + tempSocket.connected = false; + return this.updateSocketStatus(state, tempSocket); + + + default: + return super.reduce(state, action); + } + } +} + +export default new WebsocketStore(); diff --git a/src/widget/widget.js b/src/widget/widget.js index bca9e5b..1523545 100644 --- a/src/widget/widget.js +++ b/src/widget/widget.js @@ -23,6 +23,8 @@ import ICDataStore from '../ic/ic-data-store'; import ConfigsStore from '../componentconfig/config-store'; import FileStore from '../file/file-store'; import SignalStore from '../signal/signal-store' +import WebsocketStore from './websocket-store' +import ICStore from '../ic/ic-store'; import WidgetCustomAction from './widgets/custom-action'; import WidgetAction from './widgets/action'; @@ -47,11 +49,14 @@ import '../styles/widgets.css'; class Widget extends React.Component { static getStores() { - return [ ICDataStore, ConfigsStore, FileStore, SignalStore]; + return [ ICDataStore, ConfigsStore, FileStore, SignalStore, WebsocketStore, ICStore]; } static calculateState(prevState, props) { + let websockets = WebsocketStore.getState(); + let ics = ICStore.getState(); + let icData = {}; if (props.paused) { @@ -79,6 +84,8 @@ class Widget extends React.Component { } return { + ics: ics, + websockets: websockets, icData: icData, signals: signals, icIDs: icIDs, @@ -228,6 +235,8 @@ class Widget extends React.Component { return } diff --git a/src/widget/widgets/time-offset.js b/src/widget/widgets/time-offset.js index 34a91da..48017ee 100644 --- a/src/widget/widgets/time-offset.js +++ b/src/widget/widgets/time-offset.js @@ -25,7 +25,8 @@ class WidgetTimeOffset extends Component { this.state = { timeOffset: '', - icID: '' + icID: '', + websocketOpen: false }; } @@ -42,13 +43,28 @@ class WidgetTimeOffset extends Component { return {timeOffset: -1}; } + let ic = props.ics.find(ic => ic.id === parseInt(state.icID, 10)); + let websocket = props.websockets.find(ws => ws.url === ic.websocketurl); + let serverTime = props.data[state.icID].output.timestamp; let localTime = Date.now(); let absoluteOffset = Math.abs(serverTime - localTime); - return {timeOffset: Number.parseFloat(absoluteOffset/1000).toPrecision(5)}; + + if(typeof websocket === 'undefined'){ + return {timeOffset: Number.parseFloat(absoluteOffset/1000).toPrecision(5)} + } + return {timeOffset: Number.parseFloat(absoluteOffset/1000).toPrecision(5), websocketOpen: websocket.connected}; } render() { + + let icSelected = " "; + if(!this.state.websocketOpen){ + icSelected = "no connection"; + } else if (this.props.widget.customProperties.showOffset){ + icSelected = this.state.timeOffset + 's'; + } + let bottomText = this.props.widget.customProperties.icID !== -1 ? "" : "selected"; return (
@@ -56,15 +72,15 @@ class WidgetTimeOffset extends Component { (IC: {this.state.icID}) : (no IC) } - {this.props.widget.customProperties.showOffset && this.props.widget.customProperties.icID !== -1 ? + {this.props.widget.customProperties.icID !== -1 ? ( - {this.state.timeOffset}s) + {icSelected}) : - ({bottomText}) + ("selected") }
);