added zabbix integration for statistics
This commit is contained in:
112
Layout/default/Device/LiveGraph.php
Normal file
112
Layout/default/Device/LiveGraph.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Live-Graph</title>
|
||||
<style>
|
||||
body, html { margin: 0; padding: 0; width: 100%; height: 100%; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; }
|
||||
.chart-container { position: relative; width: 100%; height: 100%; padding: 10px; box-sizing: border-box; }
|
||||
.loader { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
||||
@keyframes blinker { 50% { opacity: 0; } }
|
||||
.blink_me { animation: blinker 1s linear infinite; color: #dc3545; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="chart-container">
|
||||
<canvas id="liveChartCanvas"></canvas>
|
||||
<div class="loader" id="loader">
|
||||
<p>Lade initiale Daten...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/plugins/axios/axios.min.js"></script>
|
||||
<script src="/plugins/moment/moment.min.js"></script>
|
||||
<script src="/plugins/chart.js/chart.4.4.6.js"></script>
|
||||
<script src="/plugins/chart.js/chartjs-adapter-moment.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const rxId = params.get('rx_id');
|
||||
const txId = params.get('tx_id');
|
||||
const interfaceName = params.get('name');
|
||||
const apiBaseUrl = '<?= $API_BASE_URL ?>';
|
||||
|
||||
let chartInstance = null;
|
||||
let pollInterval = null;
|
||||
|
||||
document.title = `Live: ${interfaceName}`;
|
||||
|
||||
const addPointToChart = (datasetIndex, newPoint) => {
|
||||
const dataset = chartInstance.data.datasets[datasetIndex].data;
|
||||
if (dataset.length > 0 && dataset[dataset.length - 1].x >= newPoint.x) return;
|
||||
dataset.push(newPoint);
|
||||
if (dataset.length > 120) dataset.shift(); // Keep rolling 10-minute window (120 points @ 5s interval)
|
||||
};
|
||||
|
||||
const fetchLatestValue = async (itemId) => {
|
||||
try {
|
||||
const res = await axios.get(`${apiBaseUrl}/liveData`, { params: { itemId } });
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
console.error(`Failed to fetch live data for item ${itemId}`, e);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
let isPolling = false;
|
||||
const startPolling = () => {
|
||||
pollInterval = setInterval(async () => {
|
||||
if (isPolling) return; // Prevent overlapping requests
|
||||
isPolling = true;
|
||||
const [rxPoint, txPoint] = await Promise.all([
|
||||
fetchLatestValue(rxId),
|
||||
fetchLatestValue(txId)
|
||||
]);
|
||||
if (rxPoint) addPointToChart(0, rxPoint);
|
||||
if (txPoint) addPointToChart(1, txPoint);
|
||||
chartInstance.update('none');
|
||||
isPolling = false;
|
||||
}, 250);
|
||||
};
|
||||
|
||||
const initChart = (initialData) => {
|
||||
document.getElementById('loader').style.display = 'none';
|
||||
const ctx = document.getElementById('liveChartCanvas').getContext('2d');
|
||||
chartInstance = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{ label: 'Empfangen', data: initialData[rxId] || [], borderColor: '#4CAF50', borderWidth: 1.5, pointRadius: 1, tension: 0.2, fill: true, backgroundColor: 'rgba(76, 175, 80, 0.1)' },
|
||||
{ label: 'Gesendet', data: initialData[txId] || [], borderColor: '#2196F3', borderWidth: 1.5, pointRadius: 1, tension: 0.2, fill: true, backgroundColor: 'rgba(33, 150, 243, 0.1)' }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true, maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: { type: 'time', time: { unit: 'minute', tooltipFormat: 'HH:mm:ss' } },
|
||||
y: { beginAtZero: true, title: { display: true, text: 'Mbps' } }
|
||||
},
|
||||
plugins: {
|
||||
title: { display: true, text: `Live-Traffic für ${interfaceName}`},
|
||||
legend: { position: 'bottom' }
|
||||
}
|
||||
}
|
||||
});
|
||||
startPolling();
|
||||
};
|
||||
|
||||
// Fetch initial data for the last 10 minutes
|
||||
axios.post(`${apiBaseUrl}/interfaceData`, { itemIds: [rxId, txId], timeRange: '10m' })
|
||||
.then(res => initChart(res.data))
|
||||
.catch(err => {
|
||||
document.getElementById('loader').innerText = "Fehler beim Laden der initialen Daten.";
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
window.addEventListener('beforeunload', () => clearInterval(pollInterval));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user