- smart-home/HEIZUNG.md: komplette Doku zur Ölbrenner-Erkennung (brennerstarts.py), Schwellwerte, Rekonstruktion, Dashboard-Panels, Troubleshooting - smart-home/STATE.md: klare Tabelle mit allen Dienst-URLs (public+intern) und Logins — Grafana/ioBroker/InfluxDB laufen ALLE in CT 143 auf pve-mu-3 - homelab.conf: CT_143_MU3 Beschreibung korrigiert (war "Raspi-Broker"), neue Variablen GRAFANA_URL_*/IOBROKER_URL_*/INFLUX_URL_INTERN + User/Pass (=PW_DEFAULT) damit beim nächsten Mal keine Fragen aufkommen - smart-home/scripts/: alle relevanten Skripte ins Repo: grafana_shot.js (Puppeteer-Login mit admin/astral66) add_month_panel.py (idempotente Monatskacheln im Heizung-Dashboard) brenner_rekonstruktion.py + cleanup_reconstruct.py + check_april.py patch_brenner.sh (Anpassung der Schwellwerte nach Regelkurven-Änderung) - MASTER_INDEX.md: Verweis auf HEIZUNG.md Made-with: Cursor
62 lines
2.6 KiB
Python
62 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
import json
|
|
from urllib.parse import quote
|
|
from urllib.request import urlopen
|
|
|
|
INFLUX = 'http://localhost:8086'
|
|
DB = 'iobroker'
|
|
|
|
def q(sql):
|
|
url = f'{INFLUX}/query?db={DB}&epoch=ns&q={quote(sql)}'
|
|
with urlopen(url, timeout=30) as r:
|
|
return json.loads(r.read().decode())
|
|
|
|
def rows(sql):
|
|
d = q(sql)
|
|
s = d['results'][0].get('series', [])
|
|
if not s:
|
|
return []
|
|
return s[0]['values']
|
|
|
|
from datetime import datetime, timezone, timedelta
|
|
TZ = timezone(timedelta(hours=2))
|
|
|
|
print('=== Starts im April (count) ===')
|
|
r = rows("SELECT count(value) FROM brennerstarts WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z'")
|
|
print(r)
|
|
|
|
print('\n=== Laufzeit-Summe April (Stunden) ===')
|
|
r = rows("SELECT sum(value) FROM brennerlaufzeit WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z'")
|
|
if r:
|
|
print(f' Summe = {r[0][1]:.1f} s = {r[0][1]/3600:.2f} h')
|
|
|
|
print('\n=== Pro Tag Starts und Laufzeit (April) ===')
|
|
starts = rows("SELECT count(value) FROM brennerstarts WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z' GROUP BY time(1d,-2h) fill(0)")
|
|
lauf = rows("SELECT sum(value) FROM brennerlaufzeit WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z' GROUP BY time(1d,-2h) fill(0)")
|
|
d_starts = {s[0]: s[1] or 0 for s in starts}
|
|
d_lauf = {s[0]: s[1] or 0 for s in lauf}
|
|
for ts in sorted(set(list(d_starts) + list(d_lauf))):
|
|
day = datetime.fromtimestamp(ts/1e9, TZ).date()
|
|
st = d_starts.get(ts, 0)
|
|
lf = d_lauf.get(ts, 0) / 3600
|
|
if st or lf:
|
|
print(f' {day} Starts={st:3d} Laufzeit={lf:5.2f}h Liter={lf*1.89:5.2f}')
|
|
|
|
print('\n=== verdächtig lange einzelne Laufzeiten > 1h ===')
|
|
r = rows("SELECT value FROM brennerlaufzeit WHERE value > 3600 AND time > '2026-03-01T00:00:00Z' ORDER BY time DESC LIMIT 20")
|
|
for ts, v in r:
|
|
t = datetime.fromtimestamp(ts/1e9, TZ)
|
|
print(f' {t.strftime("%Y-%m-%d %H:%M:%S")} {v:.0f}s = {v/60:.1f}min = {v/3600:.2f}h')
|
|
|
|
print('\n=== Daily max einzelne Laufzeit (wann >30min?) ===')
|
|
r = rows("SELECT max(value) FROM brennerlaufzeit WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z' GROUP BY time(1d,-2h) fill(0)")
|
|
for ts, v in r:
|
|
if v and v > 30*60:
|
|
t = datetime.fromtimestamp(ts/1e9, TZ).date()
|
|
print(f' {t} max einzel-laufzeit = {v/60:.1f} min')
|
|
|
|
print('\n=== brennerstarts value-Verteilung April ===')
|
|
r = rows("SELECT value FROM brennerstarts WHERE time >= '2026-04-01T00:00:00Z' AND time < '2026-05-01T00:00:00Z'")
|
|
vals = [x[1] for x in r]
|
|
from collections import Counter
|
|
print(f' Anzahl Zeilen = {len(vals)}, Summe = {sum(vals)}, Counter = {Counter(vals)}')
|