74 lines
2.5 KiB
JavaScript
74 lines
2.5 KiB
JavaScript
(() => {
|
|
const target = document.querySelector('#health');
|
|
const role = new URLSearchParams(location.search).get('role') || 'spectator';
|
|
let socket;
|
|
let retryIndex = 0;
|
|
let retryTimer;
|
|
let pollTimer;
|
|
const labels = {
|
|
uptime_ms: 'Время работы (мс)', wifi_state: 'Wi-Fi', rssi_dbm: 'RSSI (дБм)',
|
|
free_heap_bytes: 'Свободная память (байт)', min_free_heap_bytes: 'Мин. свободная память (байт)',
|
|
build_version: 'Версия сборки'
|
|
};
|
|
|
|
function render(health) {
|
|
target.replaceChildren();
|
|
for (const [key, label] of Object.entries(labels)) {
|
|
const term = document.createElement('dt');
|
|
const value = document.createElement('dd');
|
|
term.textContent = label;
|
|
value.textContent = health[key] ?? 'недоступно';
|
|
target.append(term, value);
|
|
}
|
|
}
|
|
|
|
async function refresh() {
|
|
try {
|
|
const response = await fetch('/api/health', { cache: 'no-store' });
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
render(await response.json());
|
|
} catch (error) {
|
|
target.textContent = `Не удалось получить состояние: ${error.message}`;
|
|
}
|
|
}
|
|
|
|
async function pollState() {
|
|
try {
|
|
const response = await fetch(`/api/state?role=${encodeURIComponent(role)}`, { cache: 'no-store' });
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
const state = await response.json();
|
|
document.title = `Морской бой — версия ${state.version}`;
|
|
} catch (_) {}
|
|
}
|
|
|
|
function beginPolling() {
|
|
if (!pollTimer) pollTimer = window.setInterval(pollState, 2000);
|
|
pollState();
|
|
}
|
|
|
|
function stopPolling() {
|
|
if (pollTimer) window.clearInterval(pollTimer);
|
|
pollTimer = undefined;
|
|
}
|
|
|
|
function connectSocket() {
|
|
socket = new WebSocket(`ws://${location.host}/ws?role=${encodeURIComponent(role)}`);
|
|
socket.onopen = () => { retryIndex = 0; stopPolling(); };
|
|
socket.onmessage = event => {
|
|
const state = JSON.parse(event.data);
|
|
document.title = `Морской бой — версия ${state.version}`;
|
|
};
|
|
socket.onclose = () => {
|
|
beginPolling();
|
|
const delays = [1000, 2000, 5000, 10000];
|
|
const delay = delays[Math.min(retryIndex++, delays.length - 1)];
|
|
retryTimer = window.setTimeout(connectSocket, delay);
|
|
};
|
|
socket.onerror = () => socket.close();
|
|
}
|
|
|
|
refresh();
|
|
window.setInterval(refresh, 5000);
|
|
connectSocket();
|
|
})();
|