// 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.|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); }, };