frontend/smart-hut/src/client_server.js

260 lines
6.8 KiB
JavaScript

// vim: set ts=2 sw=2 et tw=80:
import axios from "axios";
let config = window.BACKEND_URL || "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
}
device routes:
- 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 {
this.invokeCallbacks(data);
}
};
this.connection.onerror = (evt) => {
if (retries >= 5) {
console.error("too many socket connection retries");
return;
}
retries++;
socket = new ServiceSocket(this.token, this.callbacks);
};
}
invokeCallbacks(data) {
if (data.id && this.callbacks[data.id]) {
this.callbacks[data.id].forEach((f) => f(data));
}
}
/**
* 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);
},
register: function (data, headers) {
return axios.post(config + "register", data);
},
initResetPassword: function (data, headers) {
return axios.post(config + "register/init-reset-password", data);
},
resetPassword: function (data, headers) {
return axios.put(config + "register/reset-password", data);
},
getAllRooms: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + "room", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevices: function (token) {
if (!token) {
token = tkn;
}
return axios.get(config + "device", {
headers: { Authorization: "Bearer " + token },
});
},
getAllDevicesByRoom: function (id, token) {
if (!token) {
token = tkn;
}
return axios.get(config + "room/" + id + "/devices", {
headers: { Authorization: "Bearer " + token },
});
},
createRoom: function (data, headers) {
return axios.post(config + "room", data, {
headers: { Authorization: "Bearer " + tkn },
});
},
updateRoom: function (data, headers) {
return axios.put(config + "room/" + data.id, data, {
headers: { Authorization: "Bearer " + tkn },
});
},
deleteRoom: function (data, headers) {
return axios.delete(config + "room/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
devicePost: function (data, headers) {
return axios
.post(config + data.device, data.params, {
headers: { Authorization: "Bearer " + tkn },
})
.then((res) => {
if (res.status === 200 && data.device === "switch") {
data.params.lights.forEach((e) => {
let urlUp =
config +
data.device +
"/" +
res.data.id +
"/lights?switchableId=" +
e;
axios.post(
urlUp,
{},
{ headers: { Authorization: "Bearer " + tkn } }
);
});
}
return res;
});
},
deviceUpdate: function (data, typeDevice) {
let url = "device";
if (typeDevice) {
url = typeDevice;
}
let promiseRes = axios.put(config + url, data, {
headers: { Authorization: "Bearer " + tkn },
});
// also for btn/knob dimmer
if (typeDevice === "switch/operate") {
promiseRes = promiseRes.then((e) => {
if (e.status === 200) {
e.data.forEach((device) => socket.invokeCallbacks(device));
}
return e;
});
}
return promiseRes;
},
deviceDelete: function (data, headers) {
return axios.delete(config + data.device + "/" + data.id, {
headers: { Authorization: "Bearer " + tkn },
});
},
deviceGetById: function (data, headers) {
return axios.get(config + data.device + "/" + data.id);
},
deviceGetAll: function (data, headers) {
return axios.get(config + data.device);
},
};