#!/usr/bin/env python3 """Fuegt Oelknoten-Zeile am Heizung-Dashboard hinzu (idempotent).""" import json import subprocess BASE = "http://100.66.78.56:3000" ROW_TITLE = "🛢️ Ölknoten (Erdtrasse)" DS_UID = "ffptl25vzylfke" # InfluxDB-sensors PANEL_IDS = [901, 902, 903, 904, 905] def curl(path, method="GET", body=None): cmd = [ "curl", "-s", "-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 def stat_panel(pid, title, sensor, x, y, w=4, h=4): return { "id": pid, "type": "stat", "title": title, "datasource": {"type": "influxdb", "uid": DS_UID}, "gridPos": {"h": h, "w": w, "x": x, "y": y}, "fieldConfig": { "defaults": { "unit": "celsius", "decimals": 1, "color": {"mode": "thresholds"}, "thresholds": { "mode": "absolute", "steps": [ {"color": "blue", "value": None}, {"color": "green", "value": 10}, {"color": "orange", "value": 40}, ], }, } }, "options": { "reduceOptions": {"values": False, "calcs": ["lastNotNull"]}, "colorMode": "background", "graphMode": "none", }, "targets": [{ "refId": "A", "rawQuery": True, "query": ( f'SELECT last("value") FROM "temperature" ' f"WHERE \"node\"='oelknoten' AND \"sensor\"='{sensor}' AND $timeFilter" ), }], } d = curl("/api/dashboards/uid/heizung") dash = d["dashboard"] # Entferne alte Oelknoten-Zeile remove_titles = {ROW_TITLE, "Ölknoten Raum", "Ölknoten HK VL", "Ölknoten Erd VL", "Ölknoten Erd RL", "Ölknoten Status"} dash["panels"] = [ p for p in dash["panels"] if p.get("title") not in remove_titles and p.get("id") not in PANEL_IDS ] 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)) y = max_y dash["panels"].append({ "id": 900, "type": "row", "title": ROW_TITLE, "gridPos": {"h": 1, "w": 24, "x": 0, "y": y}, "collapsed": False, }) y += 1 panels = [ (901, "Status", None, 0), (902, "Raum", "raum", 4), (903, "HK Vorlauf", "hk_vorlauf", 8), (904, "Erd VL", "vl_erd_an", 12), (905, "Erd RL", "rl_erd_ab", 16), ] for pid, title, sensor, x in panels: if sensor is None: dash["panels"].append({ "id": pid, "type": "stat", "title": title, "datasource": {"type": "influxdb", "uid": DS_UID}, "gridPos": {"h": 4, "w": 4, "x": x, "y": y}, "fieldConfig": { "defaults": { "mappings": [ {"type": "value", "options": { "1": {"text": "ONLINE", "color": "green", "index": 0}, "0": {"text": "OFFLINE", "color": "red", "index": 1}, }}, ], "noValue": "OFFLINE", "color": {"mode": "thresholds"}, "thresholds": {"mode": "absolute", "steps": [ {"color": "red", "value": None}, {"color": "green", "value": 1}, ]}, } }, "options": { "reduceOptions": {"values": False, "calcs": ["lastNotNull"]}, "colorMode": "background", "graphMode": "none", }, "targets": [{ "refId": "A", "rawQuery": True, "query": 'SELECT last("value") FROM "node_status" WHERE "node"=\'oelknoten\'', }], }) else: dash["panels"].append(stat_panel(pid, title, sensor, x, y)) dash["version"] = dash.get("version", 0) + 1 resp = curl("/api/dashboards/db", "POST", { "dashboard": dash, "folderId": 0, "overwrite": True, "message": "Oelknoten-Zeile hinzugefuegt", }) print(json.dumps(resp, indent=2)[:500])