Discovery-Modul fuer die Messwerte des SolarManagers
Der SolarManager legt gut 130 Topics auf den Broker, aber er meldet sich nicht per Home-Assistant-Discovery. Das MQTT-Modul findet ihn deshalb nicht, und eine Automatik konnte weder auf den Netzbezug noch auf den Ladestand der Batterie oder die Temperatur im Puffer reagieren. Vier feste Geraete mit neun Messwerten, ausgewaehlt nach dem, was das Realtime-SVG zeigt - von der PV nur die Summe. Alles anzulegen haette die Auswahl im Editor unbrauchbar gemacht: jeder Wechselrichter einzeln, jeder Phasenstrom, jede Vorlauftemperatur. Netzanschluss Bezug, Einspeisung Stromzaehler Obergeschoss Leistung Solaranlage PV-Leistung, Batterie-Ladestand Pufferspeicher drei Temperaturen, Heizstab-Leistung Die beiden Modbus-Zaehler am Gen24 (meter0 am Hausanschluss, meter1 fuer das Obergeschoss) gibt es nur ueber diesen Weg - sie sprechen sonst mit niemandem. Die beiden Shelly EM3 bleiben dagegen aussen vor: die stehen ueber die Home-Assistant-Discovery laengst als Power_EG_EM_0 und Power_UG_EM_0 in der Tabelle. solarManager/eg waere ohnehin nicht dasselbe, dort ist die Wallbox im Carport eingerechnet. Beim Netzanschluss stehen Bezug und Einspeisung statt P_Grid: eine Zahl mit Vorzeichen liest sich in einer Bedingung falsch herum. Beim Obergeschoss geht das nicht, der Zaehler meldet Verbrauch negativ - das steht als Warnung im Modul. Alles nur zum Lesen. Geschaltet wird am SolarManager nichts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,8 @@ from modules.wled_module import WLEDModule
|
|||||||
from modules.mqtt_module import MQTTModule
|
from modules.mqtt_module import MQTTModule
|
||||||
from modules.shelly_module import ShellyModule
|
from modules.shelly_module import ShellyModule
|
||||||
from modules.gartenwasser_module import GartenwasserModule
|
from modules.gartenwasser_module import GartenwasserModule
|
||||||
from modules.logic_module import LogicModule #nicht Vergessen neue Module auch in Zeile 546 einzufügen!!
|
from modules.solarmanager_module import SolarManagerModule
|
||||||
|
from modules.logic_module import LogicModule #nicht Vergessen neue Module auch unten in die Liste "modules" einzufügen!!
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@@ -157,6 +158,13 @@ class Config:
|
|||||||
if not self.config.has_section('gartenwasser'):
|
if not self.config.has_section('gartenwasser'):
|
||||||
return False
|
return False
|
||||||
return self._get_bool('gartenwasser', 'enable', False)
|
return self._get_bool('gartenwasser', 'enable', False)
|
||||||
|
|
||||||
|
# SOLARMANAGER
|
||||||
|
@property
|
||||||
|
def solarmanager_enable(self) -> bool:
|
||||||
|
if not self.config.has_section('solarmanager'):
|
||||||
|
return False
|
||||||
|
return self._get_bool('solarmanager', 'enable', False)
|
||||||
|
|
||||||
|
|
||||||
# MQTT
|
# MQTT
|
||||||
@@ -580,7 +588,8 @@ def main():
|
|||||||
MQTTModule(config),
|
MQTTModule(config),
|
||||||
ShellyModule(config),
|
ShellyModule(config),
|
||||||
LogicModule(config),
|
LogicModule(config),
|
||||||
GartenwasserModule(config)
|
GartenwasserModule(config),
|
||||||
|
SolarManagerModule(config)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Jedes Modul durchlaufen
|
# Jedes Modul durchlaufen
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
SolarManager Module
|
||||||
|
Die wenigen Messwerte aus solarManager/#, die eine Automatik braucht
|
||||||
|
KEINE Datenbank-Operationen!
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import List, Dict, Tuple
|
||||||
|
from modules.base_module import BaseModule
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Wurzel aller Topics, die solarManager.py über mqttClient.publish() abgibt.
|
||||||
|
# Dasselbe Wort steht dort als Vorgabe im Quelltext; bewusst kein
|
||||||
|
# Konfigurationseintrag, er müsste in beiden Repositorien gleich lauten.
|
||||||
|
WURZEL = "solarManager"
|
||||||
|
|
||||||
|
# Aus dieser Nachricht wird hier bewusst nur ein kleiner Teil zu Messwerten.
|
||||||
|
# Sie trägt gut 130 Topics: jeden Wechselrichter einzeln, jede Strangleistung,
|
||||||
|
# jeden Phasenstrom, jede Vorlauf- und Rücklauftemperatur. Alles anzulegen
|
||||||
|
# hieße, die Auswahl im Automatik-Editor unbrauchbar zu machen - man sucht
|
||||||
|
# dann in einer Liste, statt eine Regel zu schreiben. Aufgenommen ist, was
|
||||||
|
# das Realtime-SVG auf der Solarseite anzeigt, und von der PV nur die Summe.
|
||||||
|
#
|
||||||
|
# Nicht dabei sind die beiden Shelly EM3 (Erd- und Untergeschoss). Die melden
|
||||||
|
# sich per Home-Assistant-Discovery und stehen über das MQTT-Modul längst als
|
||||||
|
# eigene Geräte in der Datenbank; ein zweiter Satz derselben Zahlen machte die
|
||||||
|
# Auswahl nur unübersichtlich. Zu beachten: solarManager/eg wäre ohnehin nicht
|
||||||
|
# dasselbe - dort ist die Wallbox im Carport mit eingerechnet.
|
||||||
|
#
|
||||||
|
# Die beiden Modbus-Zähler am Gen24 gibt es dagegen *nur* hier. Sie hängen
|
||||||
|
# unter 192.168.179.155 an derselben Adresse wie der Wechselrichter und
|
||||||
|
# sprechen sonst mit niemandem (siehe gatherModbusData.py im SolarManager,
|
||||||
|
# meter0 und meter1).
|
||||||
|
#
|
||||||
|
# Jedes dieser Topics trägt eine blanke Zahl, kein JSON - deshalb hat keiner
|
||||||
|
# der Messwerte einen value_path. Wer später einen vermisst, trägt hier eine
|
||||||
|
# Zeile ein; die vollständige Liste steht im Browser unter mqttData auf der
|
||||||
|
# Solarseite.
|
||||||
|
#
|
||||||
|
# Die URL eines Geräts ist das Topic seines ersten Messwerts. Ein eigener
|
||||||
|
# Namensraum wäre erfunden: der SolarManager kennt keine Geräte, nur Zahlen.
|
||||||
|
# Sie muss nur eindeutig sein und mit mqtt:// beginnen, damit der Runner den
|
||||||
|
# MQTT-Transport wählt; abonniert wird über die Topics der Messwerte.
|
||||||
|
GERAETE = [
|
||||||
|
{
|
||||||
|
# meter0 am Gen24, der Zähler am Hausanschluss.
|
||||||
|
#
|
||||||
|
# Bezug und Einspeisung statt P_Grid: P_Grid ist eine Zahl mit
|
||||||
|
# Vorzeichen (negativ heißt Einspeisung), und eine Bedingung darauf
|
||||||
|
# liest sich falsch herum. Diese beiden sind immer positiv, jeweils
|
||||||
|
# eine von beiden ist null.
|
||||||
|
"type": "Stromzähler",
|
||||||
|
"name": "Netzanschluss",
|
||||||
|
"messwerte": [
|
||||||
|
("Bezug", "P_GridCons", "W"),
|
||||||
|
("Einspeisung", "P_GridFeed", "W"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
# meter1 am Gen24, der Zähler für das Obergeschoss.
|
||||||
|
#
|
||||||
|
# ACHTUNG, Vorzeichen: der Zähler meldet Verbrauch negativ, und
|
||||||
|
# solarManager.py rechnet die Wallbox im Obergeschoss heraus, ohne das
|
||||||
|
# Vorzeichen zu drehen. Das Realtime-SVG zeigt deshalb -og an. Eine
|
||||||
|
# Bedingung "das Obergeschoss verbraucht mehr als 500 W" heißt hier
|
||||||
|
# also "Leistung < -500".
|
||||||
|
"type": "Stromzähler",
|
||||||
|
"name": "Stromzähler Obergeschoss",
|
||||||
|
"messwerte": [("Leistung", "og", "W")],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Solaranlage",
|
||||||
|
"name": "Solaranlage",
|
||||||
|
"messwerte": [
|
||||||
|
# Summe aller Stränge. Die einzelnen stehen in P_PVn, einem
|
||||||
|
# JSON-Feld - für eine Bedingung taugt die Summe besser, und
|
||||||
|
# genau darum ging es bei der Auswahl.
|
||||||
|
("PV-Leistung", "P_PV", "W"),
|
||||||
|
("Batterie-Ladestand", "SOC", "%"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Heizung",
|
||||||
|
"name": "Pufferspeicher",
|
||||||
|
"messwerte": [
|
||||||
|
("Temperatur oben", "t_buffT", "°C"),
|
||||||
|
("Temperatur Mitte", "t_buffM", "°C"),
|
||||||
|
("Temperatur unten", "t_buffB", "°C"),
|
||||||
|
# Was der Heizstab gerade in den Puffer schiebt. Nur zum Lesen:
|
||||||
|
# gestellt wird er über ajax/heater.php, nicht über MQTT.
|
||||||
|
("Heizstab-Leistung", "pHeat", "W"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SolarManagerModule(BaseModule):
|
||||||
|
"""
|
||||||
|
SolarManager Modul - Implementiert BaseModule Interface
|
||||||
|
|
||||||
|
Wie das Gartenwasser- und das Logic-Modul sucht dieses nichts, sondern
|
||||||
|
schreibt feste Geräte hin. Der SolarManager meldet sich nicht per
|
||||||
|
Home-Assistant-Discovery; das MQTT-Modul findet ihn also nicht, und ohne
|
||||||
|
dieses Modul kann eine Automatik weder auf den Netzbezug noch auf den
|
||||||
|
Ladestand der Batterie oder die Temperatur im Puffer reagieren.
|
||||||
|
|
||||||
|
Alles hier ist zum Lesen. Geschaltet wird am SolarManager nichts: die
|
||||||
|
Wallbox und die Heizung regelt er selbst, und wo das Web-UI eingreift,
|
||||||
|
tut es das über eigene Endpunkte (ajax/heater.php, ajax/carSteuerung.php)
|
||||||
|
und nicht über diese Topics.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_enabled(self) -> bool:
|
||||||
|
"""Prüft ob das SolarManager-Modul aktiviert ist"""
|
||||||
|
return self.config.solarmanager_enable
|
||||||
|
|
||||||
|
def discover(self) -> Tuple[List[Dict], List[Dict]]:
|
||||||
|
"""
|
||||||
|
Erzeugt die Geräte aus GERAETE - alle als Sensoren, ohne Kommandos.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple (actors, sensors)
|
||||||
|
"""
|
||||||
|
logger.info("\n" + "=" * 60)
|
||||||
|
logger.info("SOLARMANAGER-MESSWERTE WERDEN ERZEUGT")
|
||||||
|
logger.info("=" * 60)
|
||||||
|
|
||||||
|
sensoren = [self._geraet(g) for g in GERAETE]
|
||||||
|
anzahl = sum(len(g["messwerte"]) for g in GERAETE)
|
||||||
|
logger.info("%d Geräte mit %d Messwerten", len(sensoren), anzahl)
|
||||||
|
return [], sensoren
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _geraet(geraet: Dict) -> Dict:
|
||||||
|
"""Ein Gerät mit seinen Messwerten."""
|
||||||
|
states = [{
|
||||||
|
"name": name,
|
||||||
|
"url": WURZEL + "/" + topic,
|
||||||
|
"type": "float",
|
||||||
|
"unit": einheit,
|
||||||
|
} for name, topic, einheit in geraet["messwerte"]]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"type": geraet["type"],
|
||||||
|
"name": geraet["name"],
|
||||||
|
"url": "mqtt://" + states[0]["url"],
|
||||||
|
"states": states,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user