Feature: Abrechnungsperiode + Strompreise im Energie-Dashboard (v1.7.0)
- history.py: Tabelle period_starts — speichert kWh-Zählerstand zu Monats-/Jahresbeginn - main.py: price_import/price_export in Config; /api/period-energy Endpoint - Web UI: Preisfelder in Einstellungen (€/kWh Bezug + Vergütung) - Energie-Dashboard: Cards zeigen Monat/Jahr kWh + Kosten statt All-Time-Total Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import logging
|
||||
import sqlite3
|
||||
import threading
|
||||
import time
|
||||
from typing import Dict, List, Tuple
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -37,11 +37,51 @@ def init_db():
|
||||
CREATE INDEX IF NOT EXISTS idx_inv_sensor_ts
|
||||
ON measurements(inv_id, sensor_id, ts)
|
||||
""")
|
||||
# Periodenstarts: kWh-Zählerstand zu Beginn jeder Abrechungsperiode
|
||||
c.execute("""
|
||||
CREATE TABLE IF NOT EXISTS period_starts (
|
||||
agg_id TEXT NOT NULL,
|
||||
period_type TEXT NOT NULL,
|
||||
period_key TEXT NOT NULL,
|
||||
value REAL NOT NULL,
|
||||
PRIMARY KEY (agg_id, period_type, period_key)
|
||||
)
|
||||
""")
|
||||
c.commit()
|
||||
cleanup_old()
|
||||
log.info("History DB initialisiert: %s", DB_PATH)
|
||||
|
||||
|
||||
def period_key(period_type: str) -> str:
|
||||
import datetime
|
||||
now = datetime.date.today()
|
||||
return now.strftime("%Y-%m") if period_type == "monthly" else now.strftime("%Y")
|
||||
|
||||
|
||||
def save_period_start_if_new(agg_id: str, period_type: str, key: str, current_value: float):
|
||||
"""Speichert den Startwert nur wenn diese Periode noch nicht existiert."""
|
||||
with _lock:
|
||||
c = _get_conn()
|
||||
c.execute("""
|
||||
INSERT OR IGNORE INTO period_starts(agg_id, period_type, period_key, value)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (agg_id, period_type, key, current_value))
|
||||
c.commit()
|
||||
|
||||
|
||||
def get_period_consumption(agg_id: str, period_type: str, key: str,
|
||||
current_value: float) -> Optional[float]:
|
||||
"""Verbrauch seit Periodenbeginn; None wenn noch kein Startwert gespeichert."""
|
||||
with _lock:
|
||||
row = _get_conn().execute("""
|
||||
SELECT value FROM period_starts
|
||||
WHERE agg_id=? AND period_type=? AND period_key=?
|
||||
""", (agg_id, period_type, key)).fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
return max(0.0, current_value - row[0])
|
||||
|
||||
|
||||
def write_batch(inv_id: str, ts: float, values: Dict[str, float]):
|
||||
rows = [(inv_id, sid, ts, val) for sid, val in values.items()]
|
||||
with _lock:
|
||||
|
||||
Reference in New Issue
Block a user