Merge branch '54-implement-updates-with-websocket-from-backend' into 'dev'
Resolve "Implement updates with websocket from backend" Closes #54 See merge request sa4-2020/the-sanmarinoes/frontend!54
This commit is contained in:
commit
745314466d
3 changed files with 140 additions and 14 deletions
|
@ -1,33 +1,149 @@
|
||||||
|
// vim: set ts=2 sw=2 et tw=80:
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
let config = "http://localhost:8080/";
|
let config = "http://localhost:8080/";
|
||||||
var tkn = localStorage.getItem("token");
|
var tkn = localStorage.getItem("token");
|
||||||
|
|
||||||
|
/** the ServiceSocket instance valid for the current session */
|
||||||
|
var socket;
|
||||||
|
|
||||||
// requests data devices
|
// requests data devices
|
||||||
/*
|
/*
|
||||||
|
|
||||||
{
|
{
|
||||||
params : data,
|
params : data,
|
||||||
device: 'tipoDiDevice',
|
device: 'tipoDiDevice',
|
||||||
id: se serve
|
id: se serve
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
device routes:
|
device routes:
|
||||||
- buttonDimmer
|
- buttonDimmer
|
||||||
- dimmableLight
|
- dimmableLight
|
||||||
- knobDimmer
|
- knobDimmer
|
||||||
- motionSensor
|
- motionSensor
|
||||||
- regularLight
|
- regularLight
|
||||||
- sensor
|
- sensor
|
||||||
- smartPlug
|
- smartPlug
|
||||||
- switch
|
- switch
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** The number of times a connection to the socket was tried */
|
||||||
|
var retries = 0;
|
||||||
|
|
||||||
|
/** Class to handle connection with the sensor socket */
|
||||||
|
class ServiceSocket {
|
||||||
|
/**
|
||||||
|
* Create a new sensor socket connection
|
||||||
|
* @param {string} token - The JWT token (needed for authentication)
|
||||||
|
* @param {Object.<number, function>|null} callbacks - A callback map from
|
||||||
|
* device id to callback function
|
||||||
|
*/
|
||||||
|
constructor(token, callbacks) {
|
||||||
|
this.token = token;
|
||||||
|
this.authenticated = false;
|
||||||
|
this.callbacks = callbacks || {};
|
||||||
|
|
||||||
|
this.connection = new WebSocket("ws://localhost:8080/sensor-socket");
|
||||||
|
|
||||||
|
this.connection.onopen = (evt) => {
|
||||||
|
this.connection.send(JSON.stringify({ token }));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.connection.onmessage = (evt) => {
|
||||||
|
let data = JSON.parse(evt.data);
|
||||||
|
|
||||||
|
if (!this.authenticated) {
|
||||||
|
if (data.authenticated) {
|
||||||
|
this.authenticated = true;
|
||||||
|
retries = 0;
|
||||||
|
} else {
|
||||||
|
console.error("socket authentication failed");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (data.id && this.callbacks[data.id]) {
|
||||||
|
this.callbacks[data.id].forEach((f) => f(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.connection.onerror = (evt) => {
|
||||||
|
if (retries >= 5) {
|
||||||
|
console.error("too many socket connection retries");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
retries++;
|
||||||
|
socket = new ServiceSocket(this.token, this.callbacks);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new callback function to be called when updates on the device
|
||||||
|
* with the id given are recieved
|
||||||
|
* @param {number} id - the id of the device to check updates for
|
||||||
|
* @param {function} stateCallback - a function that recieves a device as the
|
||||||
|
* first parameter, that will be called whenever a update is recieved
|
||||||
|
*/
|
||||||
|
subscribe(id, stateCallback) {
|
||||||
|
if (this.callbacks[id] === undefined) {
|
||||||
|
this.callbacks[id] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.callbacks[id].push(stateCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a function previously registered with `subscribe(...)`.
|
||||||
|
* @param {number} id - the id of the device to stop checking updates for
|
||||||
|
* @param {function} stateCallback - the callback to unregister
|
||||||
|
*/
|
||||||
|
unsubscribe(id, stateCallback) {
|
||||||
|
this.callbacks[id].splice(this.callbacks[id].indexOf(stateCallback), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the underlying websocket connection
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.connection.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tkn) {
|
||||||
|
socket = new ServiceSocket(tkn);
|
||||||
|
}
|
||||||
|
|
||||||
export var call = {
|
export var call = {
|
||||||
setToken: function (token) {
|
setToken: function (token) {
|
||||||
tkn = token;
|
tkn = token;
|
||||||
|
if (tkn) {
|
||||||
|
if (socket) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
socket = new ServiceSocket(tkn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new callback function to be called when updates on the device
|
||||||
|
* with the id given are recieved
|
||||||
|
* @param {number} id - the id of the device to check updates for
|
||||||
|
* @param {function} stateCallback - a function that recieves a device as the
|
||||||
|
* first parameter, that will be called whenever a update is recieved
|
||||||
|
*/
|
||||||
|
socketSubscribe: function (id, callback) {
|
||||||
|
socket.subscribe(id, callback);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters a function previously registered with `subscribe(...)`.
|
||||||
|
* @param {number} id - the id of the device to stop checking updates for
|
||||||
|
* @param {function} stateCallback - the callback to unregister
|
||||||
|
*/
|
||||||
|
socketUnsubscribe: function (id, callback) {
|
||||||
|
socket.unsubscribe(id, callback);
|
||||||
},
|
},
|
||||||
login: function (data, headers) {
|
login: function (data, headers) {
|
||||||
return axios.post(config + "auth/login", data);
|
return axios.post(config + "auth/login", data);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// vim: set ts=2 sw=2 et tw=80:
|
||||||
|
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Grid } from "semantic-ui-react";
|
import { Grid } from "semantic-ui-react";
|
||||||
import { editButtonStyle, panelStyle } from "./devices/styleComponents";
|
import { editButtonStyle, panelStyle } from "./devices/styleComponents";
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
OPTIONAL STATE
|
OPTIONAL STATE
|
||||||
error: 2.4
|
error: 2.4
|
||||||
|
|
||||||
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold">
|
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold">
|
||||||
±{this.state.error}
|
±{this.state.error}
|
||||||
</text>
|
</text>
|
||||||
|
@ -28,6 +28,7 @@ import {
|
||||||
import { sensorText, style, valueStyle } from "./SensorStyle";
|
import { sensorText, style, valueStyle } from "./SensorStyle";
|
||||||
import Settings from "./DeviceSettings";
|
import Settings from "./DeviceSettings";
|
||||||
import { StyledDiv } from "./styleComponents";
|
import { StyledDiv } from "./styleComponents";
|
||||||
|
import { call } from "../../../client_server";
|
||||||
|
|
||||||
export default class Sensor extends Component {
|
export default class Sensor extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -37,6 +38,13 @@ export default class Sensor extends Component {
|
||||||
value: 0,
|
value: 0,
|
||||||
};
|
};
|
||||||
this.units = "";
|
this.units = "";
|
||||||
|
this.stateCallback = (e) => this.setState(Object.assign(this.state, e));
|
||||||
|
|
||||||
|
call.socketSubscribe(this.props.device.id, this.stateCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
call.socketUnsubscribe(this.props.device.id, this.stateCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
setName = () => {
|
setName = () => {
|
||||||
|
|
Loading…
Reference in a new issue