second commit

This commit is contained in:
denis
2026-03-10 13:10:32 +01:00
parent b5cc0106c6
commit 3aac7ff9b9
101 changed files with 22046 additions and 1 deletions
@@ -0,0 +1,24 @@
#relay-grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns, 3), 1fr);
gap: 0.51em;
width: 100%;
height: 100%;
padding: 0.5em;
align-items: stretch;
justify-items: stretch;
}
.relay-box {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
min-width: 320px;
}
.relay-meta {
width: 100%;
flex: 0 0 auto;
padding: .5em;
}
@@ -0,0 +1,186 @@
class RelayOverlay {
constructor(parent, relay) {
this.parent = parent;
this.relay = relay;
this.uuid = relay.uuid;
this.sockets = parent.sockets;
this.init_controls();
}
init_controls() {
this.duration_box = sId('duration-'+this.uuid);
this.start_box = sId('start-'+this.uuid);
this.stop_box = sId('stop-'+this.uuid);
this.flow_box = sId('flow-'+this.uuid);
this.ts_box = sId('ts-'+this.uuid);
this.rate_box = sId('rate-'+this.uuid);
this.remaining_box = sId('remaining-'+this.uuid);
this.duration_value = parseInt(this.duration_box.value);
this.relay_state = 0;
this.flow = 0.00;
this.start_box.onclick = () => {
this.start();
};
this.stop_box.onclick = () => {
this.stop();
};
this.duration_box.onchange = () => {
this.duration_value = parseInt(this.duration_box.value);
}
}
update(payload) {
if (payload.topic === "status") {
this.relay_state = payload.relay_state;
this.flow = parseFloat(payload.flow.toFixed(2));
this.rate = parseFloat(payload.rate.toFixed(2));
this.start_box.disabled = this.relay_state === 1;
this.stop_box.disabled = this.relay_state === 0;
if (payload.remaining>0) {
this.remaining_box.textContent = `${payload.remaining} s restante(s)`;
} else {
this.remaining_box.textContent = "";
}
this.ts_box.textContent = new Date(payload.ts * 1000).toLocaleTimeString();
this.duration_box.value = this.duration_value;
this.flow_box.textContent = this.flow;
this.rate_box.textContent = this.rate;
}
}
start() { this._send({ type: 'relay', topic: "start", value: this.duration_value }); }
stop() { this._send({ type: 'relay', topic: "stop" }); }
status() { this._send({ type: 'relay', topic: "status" }); }
halt() { this._send({ type: 'relay', topic: "halt" }); }
restart() { this._send({ type: 'relay', topic: "restart" }); }
_send(message) { this.sockets[this.uuid].send(message); }
}
class RelayManager {
constructor(container, relay) {
this.container = container;
this.relay = relay;
this.overlays = {};
this.sockets = {};
this.init_controls();
}
init_controls() {
this.all_relay_state = 0;
this.startall_box = sId('start-all');
this.stopall_box = sId('stop-all');
this.flow_box = sId('flow-all');
this.startall_box.onclick = () => {
this.all_relay_state = 1;
this._broadcast({ type: 'relay-multi', action: "start" });
};
this.stopall_box.onclick = () => {
this.all_relay_state = 0;
this._broadcast({ type: 'relay-multi', action: "stop" });
};
this.update_button();
}
async start() {
for (const relay of this.relay) {
const overlay = new RelayOverlay(this, relay);
this.overlays[relay.uuid] = overlay;
}
}
registerSocket(uuid, socket) {
this.sockets[uuid] = socket;
}
update_button() {
this.startall_box.disabled = this.all_relay_state === 1;
this.stopall_box.disabled = this.all_relay_state === 0;
}
flow_update() {
let total_flow = 0.00;
for (const relay of this.relay) {
const overlay = this.overlays[relay.uuid];
if (overlay) {
total_flow = total_flow + overlay.flow;
}
}
this.flow_box.textContent = total_flow.toFixed(2);
}
update(uuid, payload) {
const overlay = this.overlays[uuid];
if (overlay) {
overlay.update(payload);
}
}
_broadcast(message) {
if (message.type === 'relay-multi') {
const action = message.action;
this.update_button();
for (const relay of this.relay) {
const overlay = this.overlays[relay.uuid];
overlay[action]();
}
}
}
}
class MetadataSocket {
constructor(url, uuid) {
this.url = url;
this.uuid = uuid;
this.ws = null;
this.manager = null;
this.reconnectDelay = 1000;
this.shouldReconnect = true;
this.reconnect = false;
}
setOverlayManager(manager) {
this.manager = manager;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data);
this.manager.update(this.uuid, data);
this.manager.flow_update();
};
this.ws.onopen = (event) => {
const overlay = this.manager.overlays[this.uuid];
if (overlay && !this.reconnect)
overlay['status']();
this.reconnect = false;
};
this.ws.onclose = () => {
console.warn(`WebSocket closed ${this.uuid}`);
if (this.shouldReconnect) {
this.reconnect = true;
setTimeout(() => {
console.log("Reconnect WebSocket...");
this.connect();
}, this.reconnectDelay);
}
};
}
send(obj) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(obj));
}
}
}
@@ -0,0 +1,31 @@
const cpu_used = sId('cpu-used');
const shm_used = sId('shm-used');
const mem_used = sId('mem-used');
const disk_used = sId('disk-used');
const ramdisk_used = sId('ramdisk-used');
let autoTimer = null;
async function fetchStats() {
try {
const r = await fetch(stats_endpoint, { credentials: 'same-origin' });
if (!r.ok) throw new Error('HTTP ' + r.status);
const j = await r.json();
//console.log(j);
const cpu_percent = j.cpu_info.cpu_percent+'%'; cpu_used.style.setProperty("--cpu-used", cpu_percent); cpu_used.title=`Cpu: ${cpu_percent}`;
const shm_length = j.shm.length; shm_used.style.setProperty("--shm_used", shm_length); shm_used.title= `Shm: ${shm_length}`;
const virtual_memory = j.memory_info.virtual_memory.percent+'%'; mem_used.style.setProperty("--mem-used", virtual_memory); mem_used.title=`Mem: ${virtual_memory}`;
const root_percent = j.disk_info.root.percent+'%'; disk_used.style.setProperty("--disk-used", root_percent); disk_used.title=`Disk: ${root_percent}`;
let ramdisk_percent = "0%";
if (! j.ramdisk_info) ramdisk_percent = j.ramdisk_info.percent+'%';
ramdisk_used.style.setProperty("--ramdisk-used", ramdisk_percent); ramdisk_used.title=`Ramdisk: ${ramdisk_percent}`;
} catch (e) {
console.log('Error: ' + e.message);
}
}
function auto_fetch_start() { fetchStats(); autoTimer = setInterval(fetchStats, 5000);}
function auto_fetch_stop() { clearInterval(autoTimer); autoTimer = null; }
auto_fetch_start();