Files
stromverbrauch/server.js

215 lines
6.0 KiB
JavaScript

const express = require('express');
const { MongoClient, ObjectId } = require('mongodb');
const path = require('path');
const app = express();
const PORT = 3000;
// MongoDB-Verbindung
const MONGO_URL = 'mongodb://nuccy:27017';
const DB_NAME = 'smarthome';
// Konfiguration für verschiedene Collections
const COLLECTION_CONFIG = {
'maschinen': {
verbraucherFeld: 'maschine',
arbeitsFeld: 'arbeit',
zeitFeld: 'datetime',
faktor: 1, // Wh
einheit: 'Wh',
// Verbraucher-spezifische Faktoren
verbraucherFaktoren: {
'spuelmaschine': 1000 // kWh -> Wh
}
},
'auto': {
verbraucherFeld: null, // kein Verbraucher-Feld
verbraucherName: 'Auto', // fester Name
arbeitsFeld: 'gesamt',
zeitFeld: '_id', // Zeitstempel aus ObjectId
faktor: 100, // 0.1 kWh = 100 Wh
einheit: 'Wh'
}
};
let db;
// Verbindung zur MongoDB herstellen
MongoClient.connect(MONGO_URL)
.then(client => {
console.log('Erfolgreich mit MongoDB verbunden');
db = client.db(DB_NAME);
})
.catch(error => {
console.error('MongoDB Verbindungsfehler:', error);
process.exit(1);
});
// View-Engine konfigurieren
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
// Middleware
app.use(express.json());
app.use(express.static('public'));
// Hauptseite rendern
app.get('/', (req, res) => {
res.render('index');
});
// Hilfsfunktion: Zeitstempel aus Dokument extrahieren
function getTimestamp(doc, zeitFeld) {
if (zeitFeld === '_id') {
// Zeitstempel aus ObjectId extrahieren
return doc._id.getTimestamp();
}
return doc[zeitFeld];
}
// Hilfsfunktion: Query für Zeitbereich erstellen
function createTimeQuery(start, end, zeitFeld) {
if (zeitFeld === '_id') {
// Bei ObjectId: IDs im Zeitbereich generieren
const startId = ObjectId.createFromTime(Math.floor(start.getTime() / 1000));
const endId = ObjectId.createFromTime(Math.floor(end.getTime() / 1000));
return { _id: { $gte: startId, $lte: endId } };
}
return { [zeitFeld]: { $gte: start, $lte: end } };
}
// Hilfsfunktion: Daten für eine Collection abrufen
async function fetchCollectionData(collectionName, start, end) {
const config = COLLECTION_CONFIG[collectionName];
if (!config) {
return [];
}
const coll = db.collection(collectionName);
const timeQuery = createTimeQuery(start, end, config.zeitFeld);
let verbraucherList;
if (config.verbraucherFeld) {
// Alle Verbraucher im Zeitraum finden
verbraucherList = await coll.distinct(config.verbraucherFeld, timeQuery);
} else {
// Nur ein Verbraucher mit festem Namen
verbraucherList = [config.verbraucherName];
}
// Für jeden Verbraucher den ersten und letzten Wert im Zeitraum holen
const verbrauchsData = await Promise.all(
verbraucherList.map(async (verbraucher) => {
let query = { ...timeQuery };
// Verbraucher-Filter hinzufügen, falls vorhanden
if (config.verbraucherFeld) {
query[config.verbraucherFeld] = verbraucher;
}
// Sortierfeld festlegen
const sortFeld = config.zeitFeld;
// Erster Wert im Zeitraum
const ersterWert = await coll
.find(query)
.sort({ [sortFeld]: 1 })
.limit(1)
.toArray();
// Letzter Wert im Zeitraum
const letzterWert = await coll
.find(query)
.sort({ [sortFeld]: -1 })
.limit(1)
.toArray();
// Verbraucher-spezifischen Faktor prüfen
let faktor = config.faktor;
if (config.verbraucherFaktoren && config.verbraucherFaktoren[verbraucher]) {
faktor = config.verbraucherFaktoren[verbraucher];
}
const anfangsWert = (ersterWert[0][config.arbeitsFeld] || 0) * faktor;
const endWert = (letzterWert[0][config.arbeitsFeld] || 0) * faktor;
const verbrauch = endWert - anfangsWert;
return {
verbraucher: verbraucher,
collection: collectionName,
anfangsWert: anfangsWert,
anfangsZeit: getTimestamp(ersterWert[0], config.zeitFeld),
endWert: endWert,
endZeit: getTimestamp(letzterWert[0], config.zeitFeld),
verbrauch: verbrauch,
einheit: 'Wh' // Normalisiert auf Wh
};
})
);
// Null-Werte filtern (Verbraucher ohne Daten)
return verbrauchsData.filter(item => item !== null);
}
// API-Endpoint zum Abrufen der Verbrauchsdaten
app.get('/api/verbrauch', async (req, res) => {
try {
const { collections, startDate, endDate } = req.query;
if (!collections || !startDate || !endDate) {
return res.status(400).json({
error: 'Parameter fehlen: collections, startDate, endDate erforderlich'
});
}
const start = new Date(startDate);
const end = new Date(endDate);
// Ende auf 23:59:59 setzen
end.setHours(23, 59, 59, 999);
// Collections-Parameter kann kommaseparierte Liste sein
const collectionList = typeof collections === 'string'
? collections.split(',').map(c => c.trim())
: [collections];
// Daten für alle Collections abrufen
const allResults = await Promise.all(
collectionList.map(collectionName =>
fetchCollectionData(collectionName, start, end)
)
);
// Alle Ergebnisse zusammenführen
const alleVerbraucher = allResults.flat();
res.json({
zeitraum: { von: start, bis: end },
collections: collectionList,
verbraucher: alleVerbraucher
});
} catch (error) {
console.error('Fehler beim Abrufen der Daten:', error);
res.status(500).json({ error: 'Serverfehler: ' + error.message });
}
});
// API-Endpoint zum Abrufen verfügbarer Collections
app.get('/api/collections', async (req, res) => {
try {
const collections = await db.listCollections().toArray();
const collectionNames = collections.map(c => c.name);
res.json({ collections: collectionNames });
} catch (error) {
console.error('Fehler beim Abrufen der Collections:', error);
res.status(500).json({ error: 'Serverfehler: ' + error.message });
}
});
// Server starten
app.listen(PORT, () => {
console.log(`Server läuft auf http://localhost:${PORT}`);
});