Files
wetter-server/wetter.js

102 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* wetter.js Hauptprogramm
*
* Ablauf beim Start:
* 1. SQLite-Datenbank öffnen (wetter.db)
* 2. Letzten archivierten Zeitstempel lesen → Archiv nachladen
* 3. Archivdaten in DB schreiben
* 4. LOOP-Schleife starten: alle 30 s Echtzeit-Daten holen & in DB schreiben
*/
import "dotenv/config";
import path from "path";
import { fileURLToPath } from "url";
import { openDb, getLatestTs, insertRecords, insertRecord } from "./db.js";
import { readArchiveSince, connectStation, fetchLoopData } from "./davis.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DB_PATH = process.env.DB_PATH ?? path.join(__dirname, "wetter.db");
const LOOP_INTERVAL_MS = Number(process.env.LOOP_INTERVAL_MS ?? 30_000);
// ── Hilfsfunktionen ────────────────────────────────────────────────────────
const fmt24h = (d) => d.toLocaleTimeString("de-DE", { hour12: false });
const fmtDateTime = (d) => d.toLocaleString("de-DE", { hour12: false });
function log(msg) { console.log (`[${fmt24h(new Date())}] ${msg}`); }
function warn(msg) { console.warn(`[${fmt24h(new Date())}] WARN ${msg}`); }
function err(msg) { console.error(`[${fmt24h(new Date())}] ERROR ${msg}`); }
// ── Archiv nachladen ───────────────────────────────────────────────────────
async function catchUpArchive(db) {
const latestTs = getLatestTs(db);
const since = latestTs
? new Date(latestTs * 1000) // ab letztem DB-Eintrag
: new Date(Date.now() - 24 * 60 * 60 * 1000); // Fallback: letzte 24 h
log(`Lade Archiv ab ${fmtDateTime(since)} ...`);
let lastPct = -1;
const records = await readArchiveSince(since, (cur, total) => {
const pct = Math.floor(cur / total * 100);
if (pct !== lastPct) {
process.stdout.write(`\r Archiv: ${pct}% (Seite ${cur}/${total})`);
lastPct = pct;
}
});
process.stdout.write("\r\x1b[K"); // Fortschrittszeile löschen
if (records.length === 0) {
log("Archiv: keine neuen Datensätze.");
return;
}
const inserted = insertRecords(db, records, "archive");
log(`Archiv: ${inserted} neue Datensätze gespeichert (${records.length} empfangen).`);
}
// ── LOOP-Schleife ──────────────────────────────────────────────────────────
async function runLoop(db) {
let station = null;
async function connect() {
station = await connectStation();
log("Verbunden mit Wetterstation.");
}
async function tick() {
try {
const data = await fetchLoopData(station);
insertRecord(db, data, "loop");
log(
// `Außen: ${data.tempOut?.toFixed(1)}°C ` +
`InnenT: ${data.tempIn?.toFixed(1)}°C ` +
// `Feuchte: ${data.humOut}% ` +
`InnenH: ${data.humIn}% ` +
// `Wind: ${data.windAvg} km/h ` +
`Druck: ${data.pressure} hPa ` +
`Forecast: ${data.forecast}`
);
} catch (e) {
warn("LOOP-Fehler: " + e.message + " Verbindung wird neu aufgebaut.");
try { await station?.disconnect(); } catch {}
station = null;
try { await connect(); } catch (ce) { err("Reconnect fehlgeschlagen: " + ce.message); }
}
setTimeout(tick, LOOP_INTERVAL_MS);
}
await connect();
tick();
}
// ── Hauptprogramm ──────────────────────────────────────────────────────────
const db = openDb(DB_PATH);
log(`Datenbank: ${DB_PATH}`);
await catchUpArchive(db);
await runLoop(db);