Add data_visualization/js/app.js
This commit is contained in:
parent
7d688a6480
commit
eb89a6d7b9
1 changed files with 173 additions and 0 deletions
173
data_visualization/js/app.js
Normal file
173
data_visualization/js/app.js
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
import { fetchSensorData } from './api.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SensorData
|
||||||
|
* @property {string} timestamp
|
||||||
|
* @property {string} location_id
|
||||||
|
* @property {number} temperature
|
||||||
|
* @property {number} humidity
|
||||||
|
* @property {number} light
|
||||||
|
*/
|
||||||
|
|
||||||
|
let allData = [];
|
||||||
|
let chartInstances = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialisiert UI-Elemente, ruft Daten ab und rendert Diagramme.
|
||||||
|
* Wird beim Laden des Fensters aufgerufen.
|
||||||
|
*/
|
||||||
|
export async function initApp() {
|
||||||
|
try {
|
||||||
|
const data = await fetchSensorData();
|
||||||
|
if (!Array.isArray(data)) {
|
||||||
|
console.error('Ungültige Datenstruktur von /data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allData = data;
|
||||||
|
initializeFilters();
|
||||||
|
renderCharts(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Fehler beim Initialisieren der Anwendung:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialisiert Datumsauswahl- und Filter-Events.
|
||||||
|
*/
|
||||||
|
function initializeFilters() {
|
||||||
|
const startInput = document.getElementById('filter-start');
|
||||||
|
const endInput = document.getElementById('filter-end');
|
||||||
|
|
||||||
|
[startInput, endInput].forEach((input) => {
|
||||||
|
if (input) {
|
||||||
|
input.addEventListener('change', () => {
|
||||||
|
const startDate = new Date(startInput?.value);
|
||||||
|
const endDate = new Date(endInput?.value);
|
||||||
|
const filtered = filterDataByDate(allData, startDate, endDate);
|
||||||
|
updateCharts(filtered);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filtert Daten basierend auf Start- und Enddatum.
|
||||||
|
* @param {SensorData[]} data
|
||||||
|
* @param {Date} start
|
||||||
|
* @param {Date} end
|
||||||
|
* @returns {SensorData[]}
|
||||||
|
*/
|
||||||
|
function filterDataByDate(data, start, end) {
|
||||||
|
if (!(start instanceof Date) || !(end instanceof Date)) return data;
|
||||||
|
return data.filter(({ timestamp }) => {
|
||||||
|
const t = new Date(timestamp);
|
||||||
|
return t >= start && t <= end;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rendert initiale Diagramme.
|
||||||
|
* @param {SensorData[]} data
|
||||||
|
*/
|
||||||
|
function renderCharts(data) {
|
||||||
|
const ctxTemp = document.getElementById('chart-temperature');
|
||||||
|
const ctxHum = document.getElementById('chart-humidity');
|
||||||
|
const ctxLight = document.getElementById('chart-light');
|
||||||
|
|
||||||
|
const timestamps = data.map(d => new Date(d.timestamp).toLocaleTimeString());
|
||||||
|
|
||||||
|
chartInstances.temperature = new Chart(ctxTemp, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: timestamps,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Temperatur (°C)',
|
||||||
|
data: data.map(d => d.temperature),
|
||||||
|
borderColor: '#FF5733',
|
||||||
|
backgroundColor: 'rgba(255, 87, 51, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: baseChartOptions('Temperaturverlauf')
|
||||||
|
});
|
||||||
|
|
||||||
|
chartInstances.humidity = new Chart(ctxHum, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: timestamps,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Feuchtigkeit (%)',
|
||||||
|
data: data.map(d => d.humidity),
|
||||||
|
borderColor: '#33A1FF',
|
||||||
|
backgroundColor: 'rgba(51, 161, 255, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: baseChartOptions('Feuchtigkeitsverlauf')
|
||||||
|
});
|
||||||
|
|
||||||
|
chartInstances.light = new Chart(ctxLight, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: timestamps,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Lichtintensität (lx)',
|
||||||
|
data: data.map(d => d.light),
|
||||||
|
borderColor: '#FFC300',
|
||||||
|
backgroundColor: 'rgba(255, 195, 0, 0.1)',
|
||||||
|
tension: 0.3,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: baseChartOptions('Lichtintensität')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options-Vorlage für Diagramme.
|
||||||
|
* @param {string} title
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
function baseChartOptions(title) {
|
||||||
|
return {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
interaction: { mode: 'index', intersect: false },
|
||||||
|
plugins: {
|
||||||
|
title: { display: true, text: title },
|
||||||
|
tooltip: { enabled: true },
|
||||||
|
legend: { display: true }
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: { display: true, title: { display: true, text: 'Zeit' } },
|
||||||
|
y: { display: true }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aktualisiert Diagramme auf Basis neuer Filter oder Daten.
|
||||||
|
* @param {SensorData[]} filteredData
|
||||||
|
*/
|
||||||
|
export function updateCharts(filteredData) {
|
||||||
|
const timestamps = filteredData.map(d => new Date(d.timestamp).toLocaleTimeString());
|
||||||
|
|
||||||
|
if (chartInstances.temperature) {
|
||||||
|
chartInstances.temperature.data.labels = timestamps;
|
||||||
|
chartInstances.temperature.data.datasets[0].data = filteredData.map(d => d.temperature);
|
||||||
|
chartInstances.temperature.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chartInstances.humidity) {
|
||||||
|
chartInstances.humidity.data.labels = timestamps;
|
||||||
|
chartInstances.humidity.data.datasets[0].data = filteredData.map(d => d.humidity);
|
||||||
|
chartInstances.humidity.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chartInstances.light) {
|
||||||
|
chartInstances.light.data.labels = timestamps;
|
||||||
|
chartInstances.light.data.datasets[0].data = filteredData.map(d => d.light);
|
||||||
|
chartInstances.light.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', initApp);
|
||||||
Loading…
Reference in a new issue