city_breathing_measurements/data_visualization/js/app.js

173 lines
No EOL
4.6 KiB
JavaScript

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);