Update dashboard with cpu status websockets (#7400)

* Remove setting hardcoded timer

* Use websockets for real-time CPU status on dashboard

* Add system_dashboard service file

* moved javascript file to core
This commit is contained in:
frytimo
2025-06-27 18:25:32 -03:00
committed by GitHub
parent ef076f98a0
commit 807f80da94
6 changed files with 138 additions and 53 deletions

View File

@@ -0,0 +1,116 @@
class ws_client {
constructor(url, token) {
this.ws = new WebSocket(url);
this.ws.addEventListener('message', this._onMessage.bind(this));
this._nextId = 1;
this._pending = new Map();
this._eventHandlers = new Map();
// The token is submitted on every request
this.token = token;
}
// internal message handler called when event occurs on the socket
_onMessage(ev) {
let message;
let switch_event;
try {
console.log(ev.data);
message = JSON.parse(ev.data);
// check for authentication request
if (message.status_code === 407) {
console.log('Authentication Required');
return;
}
switch_event = message.payload;
//console.log('envelope received: ',env);
} catch (err) {
console.error('Error parsing JSON data:', err);
//console.error('Invalid JSON:', ev.data);
return;
}
// Pull out the request_id first
const rid = message.request_id ?? null;
// If this is the response to a pending request
if (rid && this._pending.has(rid)) {
// Destructure with defaults in case they're missing
const {
service,
topic = '',
status = 'ok',
code = 200,
payload = {}
} = message;
const {resolve, reject} = this._pending.get(rid);
this._pending.delete(rid);
if (status === 'ok' && code >= 200 && code < 300) {
resolve({service, topic, payload, code, message});
} else {
const err = new Error(message || `Error ${code}`);
err.code = code;
reject(err);
}
return;
}
// Otherwise it's a serverpushed event…
// e.g. env.service === 'event' or env.topic is your event name
this._dispatchEvent(message);
}
// Send a request to the websocket server using JSON string
request(service, topic = null, payload = {}) {
const request_id = String(this._nextId++);
const env = {
request_id: request_id,
service,
...(topic !== null ? {topic} : {}),
token: this.token,
payload: payload
};
const raw = JSON.stringify(env);
this.ws.send(raw);
return new Promise((resolve, reject) => {
this._pending.set(request_id, {resolve, reject});
// TODO: get timeout working to reject if no response in X ms
});
}
subscribe(topic) {
return this.request('active.calls', topic);
}
unsubscribe(topic) {
return this.request('active.calls', topic);
}
// register a callback for server-pushes
onEvent(topic, handler) {
console.log('registering event listener for ' + topic);
if (!this._eventHandlers.has(topic)) {
this._eventHandlers.set(topic, []);
}
this._eventHandlers.get(topic).push(handler);
}
/**
* Dispatch a serverpush event envelope to all registered handlers.
* @param {object} env
*/
_dispatchEvent(message) {
const service = message.service_name;
const topic = message.topic;
const handlers = this._eventHandlers.get(topic) || [];
for (const fn of handlers) {
try {
fn(message.payload);
} catch (err) {
console.error(`Error in handler for "${topic}":`, err);
}
}
}
}