99 lines
3.8 KiB
JavaScript
99 lines
3.8 KiB
JavaScript
/**
|
||
* 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 ` +
|
||
`Feuchte: ${data.humOut}% ` +
|
||
`Wind: ${data.windAvg} km/h ` +
|
||
`Druck: ${data.pressure} hPa`
|
||
);
|
||
} 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);
|