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";
|
||||
|
||||
let config = "http://localhost:8080/";
|
||||
var tkn = localStorage.getItem("token");
|
||||
|
||||
/** the ServiceSocket instance valid for the current session */
|
||||
var socket;
|
||||
|
||||
// requests data devices
|
||||
/*
|
||||
|
||||
{
|
||||
params : data,
|
||||
device: 'tipoDiDevice',
|
||||
id: se serve
|
||||
params : data,
|
||||
device: 'tipoDiDevice',
|
||||
id: se serve
|
||||
}
|
||||
|
||||
|
||||
device routes:
|
||||
- buttonDimmer
|
||||
- dimmableLight
|
||||
- knobDimmer
|
||||
- motionSensor
|
||||
- regularLight
|
||||
- sensor
|
||||
- smartPlug
|
||||
- switch
|
||||
- buttonDimmer
|
||||
- dimmableLight
|
||||
- knobDimmer
|
||||
- motionSensor
|
||||
- regularLight
|
||||
- sensor
|
||||
- smartPlug
|
||||
- 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 = {
|
||||
setToken: function (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) {
|
||||
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 { Grid } from "semantic-ui-react";
|
||||
import { editButtonStyle, panelStyle } from "./devices/styleComponents";
|
||||
|
|
|
@ -28,6 +28,7 @@ import {
|
|||
import { sensorText, style, valueStyle } from "./SensorStyle";
|
||||
import Settings from "./DeviceSettings";
|
||||
import { StyledDiv } from "./styleComponents";
|
||||
import { call } from "../../../client_server";
|
||||
|
||||
export default class Sensor extends Component {
|
||||
constructor(props) {
|
||||
|
@ -37,6 +38,13 @@ export default class Sensor extends Component {
|
|||
value: 0,
|
||||
};
|
||||
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 = () => {
|
||||
|
|
Loading…
Reference in a new issue