Add data_visualization/js/app.js

This commit is contained in:
Mika 2026-04-26 02:07:49 +00:00
parent 3c7ef34260
commit 556f2e22ff

View file

@ -0,0 +1,122 @@
'use strict';
/**
* Haupt-Einstiegspunkt der Anwendung zur Echtzeit-Visualisierung der WLAN-Daten.
* Initialisiert DOM, Heatmap und Event-Listener.
*/
/**
* Globale Referenzen auf DOM-Elemente und State-Objekte.
* @type {{ heatmapContainer: HTMLElement|null, refreshButton: HTMLElement|null, statsContainer: HTMLElement|null, heatmapInstance: any|null }}
*/
const appState = {
heatmapContainer: null,
refreshButton: null,
statsContainer: null,
heatmapInstance: null
};
/**
* Initialisiert UI und Listener.
*/
export async function initApp() {
appState.heatmapContainer = document.getElementById('heatmap');
appState.refreshButton = document.getElementById('refresh-btn');
appState.statsContainer = document.getElementById('stats');
if (!appState.heatmapContainer) {
console.error('Heatmap-Container nicht gefunden.');
return;
}
// Dummy Heatmap-Struktur initialisieren (z. B. Leaflet oder einfache Canvas-basierte Heatmap)
appState.heatmapInstance = createHeatmap(appState.heatmapContainer);
// Events
if (appState.refreshButton) {
appState.refreshButton.addEventListener('click', refreshData);
}
// Periodische Datenaktualisierung starten
setInterval(refreshData, 15000);
// Initial einmal rendern
await refreshData();
}
/**
* Lädt neue Daten und aktualisiert die Heatmap.
*/
export async function refreshData() {
try {
// Beispiel: lokale Datenquelle; später durch echte API ersetzt
const response = await fetch('data/heatmap_data.json');
if (!response.ok) throw new Error('Fehler beim Laden der Heatmap-Daten');
/** @type {{ points: Array<{lat: number, lng: number, rssi: number}>, stats: {min: number, max: number, avg: number} }} */
const data = await response.json();
if (appState.heatmapInstance && data?.points) {
updateHeatmap(appState.heatmapInstance, data.points);
renderStats(data.stats);
}
} catch (error) {
console.error('refreshData Fehler:', error);
}
}
/**
* Erstellt eine einfache Heatmap-Instanz.
* @param {HTMLElement} container
* @returns {object}
*/
function createHeatmap(container) {
// Platzhalter für echtes Heatmap-Rendering-Objekt
const layer = document.createElement('div');
layer.className = 'heatmap__layer';
container.appendChild(layer);
return {
container: layer,
data: [],
render(points) {
// Primitive Darstellung: Größe oder Farbe anhand RSSI simulieren
layer.innerHTML = '';
points.forEach(p => {
const point = document.createElement('div');
point.className = 'heatmap__point';
const intensity = Math.max(0, Math.min(1, (100 + p.rssi) / 100));
point.style.opacity = intensity.toFixed(2);
point.style.left = `${(p.lng % 1) * 100}%`;
point.style.top = `${(p.lat % 1) * 100}%`;
layer.appendChild(point);
});
}
};
}
/**
* Aktualisiert die Heatmap-Daten und rendert neu.
* @param {object} heatmapInstance
* @param {Array<{lat: number, lng: number, rssi: number}>} points
*/
function updateHeatmap(heatmapInstance, points) {
heatmapInstance.data = points;
heatmapInstance.render(points);
}
/**
* Rendert einfache Statistik-Anzeige.
* @param {{min: number, max: number, avg: number}} stats
*/
function renderStats(stats) {
if (!appState.statsContainer) return;
appState.statsContainer.innerHTML = `
<p><strong>Min:</strong> ${stats.min?.toFixed(1) ?? ''} dBm</p>
<p><strong>Max:</strong> ${stats.max?.toFixed(1) ?? ''} dBm</p>
<p><strong>Ø:</strong> ${stats.avg?.toFixed(1) ?? ''} dBm</p>
`;
}
// Einstiegspunkt beim Laden
window.addEventListener('load', initApp);