From 89e59d9913a968775abdd0fc4a3b47626a38838b Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Mon, 9 Dec 2024 22:08:42 +0100 Subject: [PATCH] Refactor websocket code to `$oh` namespace Signed-off-by: Florian Hotze --- .../web/src/js/openhab/index.js | 2 + .../org.openhab.ui/web/src/js/openhab/ws.js | 107 ++++++++++++++++++ .../web/src/pages/developer/log-viewer.vue | 68 +++-------- 3 files changed, 124 insertions(+), 53 deletions(-) create mode 100644 bundles/org.openhab.ui/web/src/js/openhab/ws.js diff --git a/bundles/org.openhab.ui/web/src/js/openhab/index.js b/bundles/org.openhab.ui/web/src/js/openhab/index.js index 1218a4cbca..c5950349a3 100644 --- a/bundles/org.openhab.ui/web/src/js/openhab/index.js +++ b/bundles/org.openhab.ui/web/src/js/openhab/index.js @@ -1,6 +1,7 @@ import api from './api' import auth from './auth' import sse from './sse' +import ws from './ws' import media from './media' import speech from './speech' import utils from './utils' @@ -9,6 +10,7 @@ export default { api, auth, sse, + ws, media, speech, utils diff --git a/bundles/org.openhab.ui/web/src/js/openhab/ws.js b/bundles/org.openhab.ui/web/src/js/openhab/ws.js new file mode 100644 index 0000000000..f1be3f2e05 --- /dev/null +++ b/bundles/org.openhab.ui/web/src/js/openhab/ws.js @@ -0,0 +1,107 @@ +import { getAccessToken } from './auth' + +const HEARTBEAT_MESSAGE = `{ + "type": "WebSocketEvent", + "topic": "openhab/websocket/heartbeat", + "payload": "PING", + "source": "WebSocketTestInstance" +}` + +const openWSConnections = [] + +function newWSConnection (path, messageCallback, readyCallback, errorCallback, heartbeatCallback, heartbeatInterval) { + // Create a new WebSocket connection + const socket = new WebSocket(path + `?access_token=${getAccessToken()}`) + socket.path = path + + // Handle WebSocket connection opened + socket.onopen = (event) => { + socket.setKeepalive(heartbeatInterval) + if (readyCallback) { + readyCallback(event) + } + } + + // Handle WebSocket message received + socket.onmessage = (event) => { + let evt = event.data + try { + evt = JSON.parse(event.data) + } catch (e) { + console.error('Error while parsing message', e) + } + messageCallback(evt) + } + + // Handle WebSocket error + socket.onerror = (event) => { + console.error('WebSocket error', event) + if (errorCallback) { + errorCallback(event) + } + } + + // WebSocket keep alive + socket.setKeepalive = (seconds = 5) => { + console.debug('Setting keepalive interval seconds', seconds) + socket.clearKeepalive() + socket.keepaliveTimer = setTimeout(() => { + console.warn('WebSocket timeout error') + if (heartbeatCallback) { + heartbeatCallback() + } else { + socket.send(HEARTBEAT_MESSAGE) + } + }, (seconds + 2) * 1000) + } + + socket.clearKeepalive = () => { + if (socket.keepaliveTimer) clearTimeout(socket.keepaliveTimer) + delete socket.keepaliveTimer + } + + // Add the new WebSocket connection to the list + openWSConnections.push(socket) + console.debug(`new WS connection: ${socket.path}, ${openWSConnections.length} open connections`) + console.debug(openWSConnections) + + return socket +} + +export default { + /** + * Connect to the websocket at the given path. + * + * @param {string} path path to connect to, e.g. `/ws` + * @param {fn} messageCallback + * @param {fn} [readyCallback=null] + * @param {fn} [errorCallback=null] + * @param {fn} [heartbeatCallback=null] heartbeat callback to use instead of the default PING/PONG + * @param {number} [heartbeatInterval=5] heartbeat interval in seconds + * @return {WebSocket} + */ + connect (path, messageCallback, readyCallback = null, errorCallback = null, heartbeatCallback = null, heartbeatInterval = 5) { + return newWSConnection(path, messageCallback, readyCallback, errorCallback, heartbeatCallback, heartbeatInterval) + }, + /** + * Close the given websocket connection. + * + * @param {WebSocket} socket + * @param {fn} [callback=null] callback to execute on connection close + */ + close (socket, callback = null) { + if (!socket) return + if (openWSConnections.indexOf(socket) >= 0) { + openWSConnections.splice(openWSConnections.indexOf(socket), 1) + } + console.debug(`WS connection closed: ${socket.path}, ${openWSConnections.length} open connections`) + console.debug(openWSConnections) + socket.onclose = (event) => { + if (callback) { + callback(event) + } + } + socket.close() + socket.clearKeepalive() + } +} diff --git a/bundles/org.openhab.ui/web/src/pages/developer/log-viewer.vue b/bundles/org.openhab.ui/web/src/pages/developer/log-viewer.vue index 61475180c6..c75cf07614 100644 --- a/bundles/org.openhab.ui/web/src/pages/developer/log-viewer.vue +++ b/bundles/org.openhab.ui/web/src/pages/developer/log-viewer.vue @@ -327,24 +327,14 @@