homelab-brain/smart-home/scripts/add_month_panel.py
root b61ac66367 docs(smart-home): dokumentiere Heizung/Brenner komplett, alle Zugänge in homelab.conf
- 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
2026-04-20 22:31:32 +02:00

114 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""Fuegt 'Ölverbrauch je Heizmonat' Panel am unteren Dashboard-Rand hinzu (idempotent)."""
import json, subprocess, string
from datetime import date
BASE='http://100.66.78.56:3000'
PANEL_TITLE='Ölverbrauch je Heizmonat (Liter)'
PANEL_ID=900
def curl(path, method='GET', body=None):
cmd=['curl','-s','--socks5-hostname','127.0.0.1:1055','-u','admin:astral66',
'-X',method,f'{BASE}{path}']
if body is not None:
cmd+=['-H','Content-Type: application/json','-d',json.dumps(body)]
r=subprocess.run(cmd,capture_output=True,text=True,timeout=30)
return json.loads(r.stdout) if r.stdout.startswith(('[','{')) else r.stdout
# Welche Monate? Alle Kalendermonate ab erstem Monat mit Daten (Jan 2026) bis heute.
# Damit wir nicht manuell nachpflegen muessen, generieren wir alle Monate von Jan 2026 bis today.month+1
START_Y, START_M = 2026, 1
today = date.today()
months = []
y, m = START_Y, START_M
while (y, m) <= (today.year, today.month):
months.append((y, m))
y, m = (y+1, 1) if m == 12 else (y, m+1)
print('Monate:', months)
def alphabet(i):
# A,B,...,Z,AA,AB,...
if i < 26:
return string.ascii_uppercase[i]
return string.ascii_uppercase[i//26 - 1] + string.ascii_uppercase[i % 26]
MON_DE = ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez']
targets = []
overrides = []
for i, (y, m) in enumerate(months):
ref = alphabet(i)
ny, nm = (y+1, 1) if m == 12 else (y, m+1)
q = (f"SELECT sum(\"value\") / 3600 * 1.89 FROM \"brennerlaufzeit\" "
f"WHERE time >= '{y}-{m:02d}-01T00:00:00Z' AND time < '{ny}-{nm:02d}-01T00:00:00Z'")
targets.append({'query': q, 'rawQuery': True, 'refId': ref})
overrides.append({
'matcher': {'id': 'byFrameRefID', 'options': ref},
'properties': [
{'id': 'displayName', 'value': f'{MON_DE[m-1]} {y}'},
]
})
# Get current dashboard
d = curl('/api/dashboards/uid/heizung')
dash = d['dashboard']
# Max y+h
max_y = 0
for p in dash['panels']:
gp = p.get('gridPos', {})
max_y = max(max_y, gp.get('y', 0) + gp.get('h', 0))
# Remove existing panel with same title (idempotent)
dash['panels'] = [p for p in dash['panels']
if p.get('title') not in (PANEL_TITLE, 'Ölverbrauch je Heizmonat')
and p.get('id') != PANEL_ID]
new_panel = {
'id': PANEL_ID,
'type': 'stat',
'title': PANEL_TITLE,
'datasource': 'InfluxDB',
'gridPos': {'x': 0, 'y': max_y, 'w': 24, 'h': 5},
'fieldConfig': {
'defaults': {
'decimals': 1,
'unit': 'none',
'color': {'mode': 'thresholds'},
'thresholds': {'mode': 'absolute', 'steps': [
{'value': None, 'color': 'green'},
{'value': 100, 'color': 'orange'},
{'value': 250, 'color': 'red'},
]},
},
'overrides': overrides,
},
'options': {
'colorMode': 'background_solid',
'graphMode': 'none',
'justifyMode': 'center',
'reduceOptions': {
'calcs': ['lastNotNull'],
'fields': '',
'values': False,
},
'textMode': 'value_and_name',
'orientation': 'vertical',
'text': {
'titleSize': 14,
'valueSize': 32,
},
'wideLayout': True,
'percentChangeColorMode': 'standard',
},
'targets': targets,
}
dash['panels'].append(new_panel)
resp = curl('/api/dashboards/db', 'POST', {
'dashboard': dash,
'overwrite': True,
'message': f'add monthly oil consumption tiles ({len(months)} months)',
})
print(resp)