This commit is contained in:
Mateusz Gruszczyński
2026-02-03 21:43:42 +01:00
commit e3724e1249
12 changed files with 474 additions and 0 deletions

117
static/js/monitor.js Normal file
View File

@@ -0,0 +1,117 @@
const socket = io();
let currentTimeRange = '6h';
let phasesConfig = {};
const gauges = {};
let voltageChart = null;
const THRESHOLDS = { min: 207, max: 253 };
function initMonitor(phases, defaultRange) {
phasesConfig = phases;
currentTimeRange = defaultRange;
const gaugeConfig = {
type: 'doughnut',
data: {
datasets: [{
data: [0, 100],
backgroundColor: ['#198754', '#1a1d20'],
borderWidth: 0,
circumference: 180,
rotation: 270
}]
},
options: {
responsive: true,
maintainAspectRatio: true,
cutout: '75%',
plugins: { legend: { display: false }, tooltip: { enabled: false } }
}
};
Object.keys(phasesConfig).forEach(id => {
const canvas = document.getElementById('gauge' + id);
if (canvas) {
gauges[id] = new Chart(canvas, JSON.parse(JSON.stringify(gaugeConfig)));
updateGaugeUI(id, 230);
}
});
const ctxChart = document.getElementById('voltageChart');
if (ctxChart) {
voltageChart = new Chart(ctxChart, {
type: 'line',
data: {
datasets: Object.keys(phasesConfig).map(id => ({
label: phasesConfig[id].label,
data: [],
borderColor: phasesConfig[id].color,
backgroundColor: phasesConfig[id].color + '20',
tension: 0.3,
pointRadius: 0,
borderWidth: 2
}))
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
type: 'time',
time: {
displayFormats: { hour: 'HH:mm', minute: 'HH:mm' },
tooltipFormat: 'HH:mm'
},
grid: { color: '#2d3139' }
},
y: { min: 190, max: 270, grid: { color: '#2d3139' }, ticks: { stepSize: 10 } }
}
}
});
}
socket.on('voltage_update', function(data) {
Object.keys(phasesConfig).forEach(id => {
const val = data['phase' + id];
const textElement = document.getElementById('value' + id);
if (val !== undefined && val !== null && val !== 0) {
const numVal = parseFloat(val);
if (textElement) textElement.textContent = numVal.toFixed(1) + 'V';
updateGaugeUI(id, numVal);
}
});
if (data.timestamp) {
const date = new Date(data.timestamp);
document.getElementById('lastUpdate').textContent = 'Odczyt: ' + date.toLocaleTimeString('pl-PL', {hour: '2-digit', minute:'2-digit', second:'2-digit', hour12: false});
}
});
window.changeTimeRange(currentTimeRange);
}
function updateGaugeUI(id, val) {
if (!gauges[id]) return;
const percentage = Math.max(0, Math.min(100, ((val - 190) / 80) * 100));
let color = '#198754';
if (val < THRESHOLDS.min || val > THRESHOLDS.max) color = '#dc3545';
else if (val < 212 || val > 248) color = '#ffc107';
gauges[id].data.datasets[0].data = [percentage, 100 - percentage];
gauges[id].data.datasets[0].backgroundColor = [color, '#1a1d20'];
gauges[id].update('none');
}
window.changeTimeRange = async function(range) {
currentTimeRange = range;
document.querySelectorAll('.time-btn').forEach(btn => btn.classList.remove('active'));
const activeBtn = document.querySelector(`[data-range="${range}"]`);
if (activeBtn) activeBtn.classList.add('active');
if (!voltageChart) return;
for (let i = 1; i <= Object.keys(phasesConfig).length; i++) {
try {
const response = await fetch(`/api/timeseries/${i}?range=${range}`);
const data = await response.json();
voltageChart.data.datasets[i-1].data = data.map(d => ({ x: new Date(d.time), y: d.voltage }));
} catch (e) { console.error(e); }
}
voltageChart.update();
};