Grafana-Tool: Temperaturen, Energie, Heizung live aus InfluxDB
This commit is contained in:
parent
65fe32aa49
commit
156cb92e26
1 changed files with 188 additions and 7 deletions
|
|
@ -1,21 +1,80 @@
|
||||||
"""Grafana Monitoring Dashboard Tool."""
|
"""Grafana + InfluxDB Smart-Home Tool (CT 143, pve-mu-3)."""
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
GRAFANA_URL = "http://100.66.78.56:3000"
|
||||||
|
GRAFANA_USER = "admin"
|
||||||
|
GRAFANA_PASS = "astral66"
|
||||||
|
INFLUX_URL = "http://100.66.78.56:8086"
|
||||||
|
INFLUX_DB = "iobroker"
|
||||||
|
|
||||||
|
SENSOR_MAP = {
|
||||||
|
"aussen": ("mqtt.0.Holzvergaser_Sensoren_6.Aussenfühler.temperature", "Aussen"),
|
||||||
|
"wohnstube": ("mqtt.0.Wohnstube_Temperatur_1.Wohnstube.Wohnstube_Temperatur", "Wohnstube"),
|
||||||
|
"kueche": ("mqtt.0.ESP_Kücheneu_2.Sensor_Küche.Küche", "Kueche"),
|
||||||
|
"garage": ("mqtt.0.ESP_Easy_3.Garage_neu.Garage", "Garage"),
|
||||||
|
"puffer_oben": ("mqtt.0.ESP_Easy_Display_4.oben.temperature", "Puffer oben"),
|
||||||
|
"puffer_unten": ("mqtt.0.ESP_Easy_Display_4.Unten.temperature", "Puffer unten"),
|
||||||
|
"garten": ("mqtt.0.ESP_Easy_schwimmbad_neu.Lufttemperatur.Lufttemperatur_Garten", "Garten/Luft"),
|
||||||
|
"schwimmbad": ("mqtt.0.ESP_Easy_schwimmbad_neu.Schwimmbad.Wassertemperatur_", "Schwimmbad"),
|
||||||
|
"oelkessel_vl": ("mqtt.0.Oelkessel.Oelkessel_VL.Vorlauf", "Oelkessel Vorlauf"),
|
||||||
|
"brunnen_vl": ("mqtt.0.Brunnenwasser.Oelkessel_VL.Vorlauf", "Brunnenwasser Vorlauf"),
|
||||||
|
"holzvergaser_1": ("mqtt.0.Holzvergaser_Sensoren_6.temp1.temperature1", "Holzvergaser Sensor 1"),
|
||||||
|
"holzvergaser_2": ("mqtt.0.Holzvergaser_Sensoren_6.temp2.temperature2", "Holzvergaser Sensor 2"),
|
||||||
|
}
|
||||||
|
|
||||||
|
ENERGIE_MEASUREMENTS = {
|
||||||
|
"pv_leistung": ("mqtt.1.openWB.pv.W", "PV Leistung (W)"),
|
||||||
|
"pv_tagesertrag": ("mqtt.1.openWB.pv.DailyYieldKwh", "PV Tagesertrag (kWh)"),
|
||||||
|
"netz_bezug": ("mqtt.1.openWB.evu.W", "Netz Bezug/Einspeisung (W)"),
|
||||||
|
"hausverbrauch": ("mqtt.1.openWB.global.WHouseConsumption", "Hausverbrauch (W)"),
|
||||||
|
"batterie_soc": ("mqtt.1.openWB.housebattery.%Soc", "Batterie SoC (%)"),
|
||||||
|
"ueberschuss": ("mqtt.1.openWB.SmartHome.Status.uberschuss", "Ueberschuss (W)"),
|
||||||
|
}
|
||||||
|
|
||||||
TOOLS = [
|
TOOLS = [
|
||||||
{
|
{
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "get_grafana_status",
|
"name": "get_grafana_status",
|
||||||
"description": "Grafana Monitoring-Status: Health, Dashboards, Datasources, Alerts. Nutze bei 'Grafana', 'Monitoring Dashboard', 'Alerts'.",
|
"description": "Grafana Monitoring-Status: Health, Dashboards, Datasources, Alerts.",
|
||||||
|
"parameters": {"type": "object", "properties": {}, "required": []},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_temperaturen",
|
||||||
|
"description": "Aktuelle Temperaturen aus dem Haus in Muldenstein: Raeume, Aussen, Puffer, Heizung. Nutze bei Fragen zu Temperatur, Heizung, Puffer, Raumklima, 'wie warm ist es'.",
|
||||||
|
"parameters": {"type": "object", "properties": {}, "required": []},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_energie",
|
||||||
|
"description": "Aktuelle Energiedaten: PV-Leistung, Batterie, Hausverbrauch, Netz. Nutze bei Fragen zu Solar, PV, Strom, Energie, Batterie, Wallbox, Einspeisung.",
|
||||||
|
"parameters": {"type": "object", "properties": {}, "required": []},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "get_heizung",
|
||||||
|
"description": "Heizungsstatus: Brenner, Puffertemperaturen, Vorlauf, Holzvergaser. Nutze bei Fragen zu Heizung, Brenner, Puffer, Holzvergaser, Oelkessel.",
|
||||||
"parameters": {"type": "object", "properties": {}, "required": []},
|
"parameters": {"type": "object", "properties": {}, "required": []},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
GRAFANA_URL = "http://100.66.78.56:3000"
|
SYSTEM_PROMPT_EXTRA = """Fuer Smart-Home-Daten (Temperaturen, Energie, Heizung) im Haus Muldenstein:
|
||||||
GRAFANA_USER = "admin"
|
- get_temperaturen: alle Raumtemperaturen + Aussen
|
||||||
GRAFANA_PASS = "astral66"
|
- get_energie: PV, Batterie, Netz, Hausverbrauch
|
||||||
|
- get_heizung: Brenner, Puffer, Vorlauf, Holzvergaser
|
||||||
|
- get_grafana_status: Dashboard-Uebersicht und Alerts
|
||||||
|
Grafana-URL: https://grafana.orbitalo.net/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _api(path):
|
def _api(path):
|
||||||
|
|
@ -27,9 +86,44 @@ def _api(path):
|
||||||
)
|
)
|
||||||
if r.ok:
|
if r.ok:
|
||||||
return r.json()
|
return r.json()
|
||||||
return None
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _influx_query(q):
|
||||||
|
try:
|
||||||
|
r = requests.get(
|
||||||
|
f"{INFLUX_URL}/query",
|
||||||
|
params={"db": INFLUX_DB, "q": q},
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
if r.ok:
|
||||||
|
return r.json()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _query_latest(measurements: dict) -> list:
|
||||||
|
"""Query last() for a dict of {key: (measurement, label)}."""
|
||||||
|
parts = []
|
||||||
|
for key, (meas, label) in measurements.items():
|
||||||
|
parts.append(f'last(value) AS "{label}" FROM "{meas}"')
|
||||||
|
q = "SELECT " + "; SELECT ".join(parts) + " WHERE time > now() - 2h"
|
||||||
|
result = _influx_query(q)
|
||||||
|
if not result:
|
||||||
|
return []
|
||||||
|
lines = []
|
||||||
|
for stmt in result.get("results", []):
|
||||||
|
for series in stmt.get("series", []):
|
||||||
|
name = series["columns"][1] if len(series["columns"]) > 1 else series.get("name", "?")
|
||||||
|
val = series["values"][0][1] if series.get("values") else None
|
||||||
|
ts = series["values"][0][0] if series.get("values") else ""
|
||||||
|
if val is not None:
|
||||||
|
ts_short = ts[11:16] if len(ts) > 16 else ""
|
||||||
|
lines.append((name, val, ts_short))
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
def handle_get_grafana_status(**kw):
|
def handle_get_grafana_status(**kw):
|
||||||
|
|
@ -65,6 +159,93 @@ def handle_get_grafana_status(**kw):
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_get_temperaturen(**kw):
|
||||||
|
data = _query_latest(SENSOR_MAP)
|
||||||
|
if not data:
|
||||||
|
return "Keine Temperaturdaten verfuegbar (InfluxDB nicht erreichbar?)"
|
||||||
|
|
||||||
|
raeume = []
|
||||||
|
heizung = []
|
||||||
|
for name, val, ts in data:
|
||||||
|
entry = f" {name}: {val:.1f} C ({ts})"
|
||||||
|
if any(k in name.lower() for k in ["puffer", "vorlauf", "holz", "brunnen", "oel"]):
|
||||||
|
heizung.append(entry)
|
||||||
|
else:
|
||||||
|
raeume.append(entry)
|
||||||
|
|
||||||
|
lines = ["Temperaturen Muldenstein (live):"]
|
||||||
|
if raeume:
|
||||||
|
lines.append("\nRaeume & Aussen:")
|
||||||
|
lines.extend(raeume)
|
||||||
|
if heizung:
|
||||||
|
lines.append("\nHeizung & Puffer:")
|
||||||
|
lines.extend(heizung)
|
||||||
|
lines.append(f"\nGrafana: https://grafana.orbitalo.net/d/solar/raumtemperaturen")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_get_energie(**kw):
|
||||||
|
data = _query_latest(ENERGIE_MEASUREMENTS)
|
||||||
|
if not data:
|
||||||
|
return "Keine Energiedaten verfuegbar (InfluxDB nicht erreichbar?)"
|
||||||
|
|
||||||
|
lines = ["Energie Muldenstein (live):\n"]
|
||||||
|
for name, val, ts in data:
|
||||||
|
if "%" in name or "kWh" in name:
|
||||||
|
lines.append(f" {name}: {val:.1f} ({ts})")
|
||||||
|
else:
|
||||||
|
lines.append(f" {name}: {val:.0f} ({ts})")
|
||||||
|
|
||||||
|
lines.append(f"\nGrafana: https://grafana.orbitalo.net/d/solar/energie-uebersicht")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_get_heizung(**kw):
|
||||||
|
heiz_sensors = {
|
||||||
|
"puffer_oben": SENSOR_MAP["puffer_oben"],
|
||||||
|
"puffer_unten": SENSOR_MAP["puffer_unten"],
|
||||||
|
"oelkessel_vl": SENSOR_MAP["oelkessel_vl"],
|
||||||
|
"brunnen_vl": SENSOR_MAP["brunnen_vl"],
|
||||||
|
"holzvergaser_1": SENSOR_MAP["holzvergaser_1"],
|
||||||
|
"holzvergaser_2": SENSOR_MAP["holzvergaser_2"],
|
||||||
|
"aussen": SENSOR_MAP["aussen"],
|
||||||
|
}
|
||||||
|
data = _query_latest(heiz_sensors)
|
||||||
|
|
||||||
|
brenner_q = 'SELECT last(value) FROM "brennerstatus" WHERE time > now() - 2h'
|
||||||
|
laufzeit_q = 'SELECT last(value) FROM "brenner_heute" WHERE time > now() - 2h'
|
||||||
|
starts_q = 'SELECT last(value) FROM "brennerstarts" WHERE time > now() - 24h'
|
||||||
|
|
||||||
|
lines = ["Heizung Muldenstein (live):\n"]
|
||||||
|
|
||||||
|
brenner = _influx_query(brenner_q)
|
||||||
|
if brenner and brenner.get("results", [{}])[0].get("series"):
|
||||||
|
val = brenner["results"][0]["series"][0]["values"][0][1]
|
||||||
|
status = "AN" if val else "AUS"
|
||||||
|
lines.append(f" Brenner: {status}")
|
||||||
|
|
||||||
|
laufzeit = _influx_query(laufzeit_q)
|
||||||
|
if laufzeit and laufzeit.get("results", [{}])[0].get("series"):
|
||||||
|
val = laufzeit["results"][0]["series"][0]["values"][0][1]
|
||||||
|
lines.append(f" Brenner heute: {val:.0f} min")
|
||||||
|
|
||||||
|
starts = _influx_query(starts_q)
|
||||||
|
if starts and starts.get("results", [{}])[0].get("series"):
|
||||||
|
val = starts["results"][0]["series"][0]["values"][0][1]
|
||||||
|
lines.append(f" Brennerstarts: {val:.0f}")
|
||||||
|
|
||||||
|
if data:
|
||||||
|
lines.append("")
|
||||||
|
for name, val, ts in data:
|
||||||
|
lines.append(f" {name}: {val:.1f} C ({ts})")
|
||||||
|
|
||||||
|
lines.append(f"\nGrafana: https://grafana.orbitalo.net/d/heizung/heizung-and-puffer")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
HANDLERS = {
|
HANDLERS = {
|
||||||
"get_grafana_status": handle_get_grafana_status,
|
"get_grafana_status": handle_get_grafana_status,
|
||||||
|
"get_temperaturen": handle_get_temperaturen,
|
||||||
|
"get_energie": handle_get_energie,
|
||||||
|
"get_heizung": handle_get_heizung,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue