mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
Time Offset Widget: check connection status #208
This commit is contained in:
parent
04ebd23d8f
commit
794082320a
4 changed files with 109 additions and 9 deletions
|
@ -14,6 +14,8 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
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);
|
||||
}
|
||||
|
|
59
src/widget/websocket-store.js
Normal file
59
src/widget/websocket-store.js
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
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();
|
|
@ -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 <WidgetTimeOffset
|
||||
widget={widget}
|
||||
data={this.state.icData}
|
||||
websockets={this.state.websockets}
|
||||
ics={this.state.ics}
|
||||
/>
|
||||
}
|
||||
|
||||
|
|
|
@ -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 (
|
||||
<div className="time-offset">
|
||||
|
@ -56,15 +72,15 @@ class WidgetTimeOffset extends Component {
|
|||
(<span>IC: {this.state.icID}</span>) : (<span>no IC</span>)
|
||||
}
|
||||
<TrafficLight Horizontal={this.props.widget.customProperties.horizontal} width={this.props.widget.width} height={this.props.widget.height}
|
||||
RedOn={this.props.widget.customProperties.threshold_red <= this.state.timeOffset}
|
||||
YellowOn={(this.props.widget.customProperties.threshold_yellow <= this.state.timeOffset) && (this.state.timeOffset < this.props.widget.customProperties.threshold_red)}
|
||||
GreenOn={this.state.timeOffset < this.props.widget.customProperties.threshold_yellow}
|
||||
RedOn={(this.props.widget.customProperties.threshold_red <= this.state.timeOffset) || !this.state.websocketOpen}
|
||||
YellowOn={(this.props.widget.customProperties.threshold_yellow <= this.state.timeOffset) && (this.state.timeOffset < this.props.widget.customProperties.threshold_red) && this.state.websocketOpen}
|
||||
GreenOn={(this.state.timeOffset < this.props.widget.customProperties.threshold_yellow) && this.state.websocketOpen}
|
||||
/>
|
||||
{this.props.widget.customProperties.showOffset && this.props.widget.customProperties.icID !== -1 ?
|
||||
{this.props.widget.customProperties.icID !== -1 ?
|
||||
(
|
||||
<span>{this.state.timeOffset}s</span>)
|
||||
<span>{icSelected}</span>)
|
||||
:
|
||||
(<span>{bottomText}</span>)
|
||||
(<span>"selected"</span>)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
|
Loading…
Add table
Reference in a new issue