Wechselrichter per MQTT

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Wechselrichter per MQTT

Beitrag von Snatsch »

Hallo, Ich habe gestern mein Balkonkraftwerk installiert und per MQTT in openhab eingebunden. Ich habe drei Kanäle eingebunden

Code: Alles auswählen

UID: mqtt:topic:MQTTBroker:Solar
label: Solar
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:MQTTBroker
location: Garten
channels:
  - id: SolarAktuell
    channelTypeUID: mqtt:number
    label: Solar Aktuell
    description: ""
    configuration:
      stateTopic: solar/power
  - id: SolarHeute
    channelTypeUID: mqtt:number
    label: Solar Heute
    description: ""
    configuration:
      stateTopic: solar/total_today
  - id: SolarGesamt
    channelTypeUID: mqtt:number
    label: "Solar Gesamt "
    description: ""
    configuration:
      stateTopic: solar/total
welche auch Daten bringen. Dann habe ich folgendes Skript aus diesen Forum im Hintergrund laufen.

Code: Alles auswählen

#!/bin/bash
TMP=/tmp/.grab.$$
USER=admin
PASSWORD=admin
IPINVERTER=192.168.2.154
MQTT=192.168.2.200
SLEEP=5
while [ 1 ]
do
	curl --silent --user ${USER}:${PASSWORD} http://${IPINVERTER}/status.html > $TMP
	if [ $? = 0 ]; then
		CUR_POW=`grep "var webdata_now_p" $TMP | cut -d\" -f2`
		YIE_TOD=`grep "var webdata_today_e" $TMP | cut -d\" -f2`
		YIE_TOT=`grep "var webdata_total_e" $TMP | cut -d\" -f2`
		mosquitto_pub -h ${MQTT} -t solar/power -m "$CUR_POW" -q 1
		mosquitto_pub -h ${MQTT} -t solar/total_today -m "$YIE_TOD" -q 1
		mosquitto_pub -h ${MQTT} -t solar/total -m "$YIE_TOT" -q 1
	fi
	sleep ${SLEEP}
done
meine erste Frage ob es Sinnvoll ist das Skript alle 5 Sekunden durchlaufen zu lassen ?
Ich Errechne mit eurer Hilfe meinen Gasverbrauch per Rule Jetzt dachte ich das ich das auch mit dem Solarertrag machen kann und habe folgende Items angelegt.

Code: Alles auswählen

Group Solarertrag
String Solarertrag_Heute_Item "SolarHeute" <solarplant> (Solarertrag)
String Solarertrag_Woche_Item "SolarWoche"<solarplant> (Solarertrag)
String Solarertrag_Monat_Item "SolarMonat"<solarplant> (Solarertrag)
String Solarertrag_Jahr_Item "SolarJahr"<solarplant> (Solarertrag)
und folgende Rule umgeschrieben.

Code: Alles auswählen

rule "Solarertrag Tag Woche Monat Jahr" // Deutscher Zeichensatz zulässig
when
    Item Solar_Solar_Gesamt_ changed // changed reicht.
then
   
    val Preis = 0.481 
    val ZonedDateTime zdt = ZonedDateTime.now() // jetzt
    val ZonedDateTime start_of_day = zdt.with(LocalTime.MIDNIGHT) // heute, Mitternacht
    val ZonedDateTime start_of_week = start_of_day.minusDays(start_of_day.getDayOfWeek.getValue - 1) // Montag
    val ZonedDateTime start_of_month = start_of_day.withDayOfMonth(1) // Erster Tag des Monats (1)
    val ZonedDateTime start_of_year = start_of_day.withDayOfYear(89) // Läuft seit 29.03.2024
    
    val float Solarertrag_Heute = (Solar__Solar_Aktuell.deltaSince(start_of_day) as Number).floatValue // kWh Delta holen
    val float Solarertrag_Woche = (Solar__Solar_Aktuell.deltaSince(start_of_week) as Number).floatValue
    val float Solarertrag_Monat = (Solar__Solar_Aktuell.deltaSince(start_of_month) as Number).floatValue
    val float Solarertrag_Jahr = (Solar__Solar_Aktuell.deltaSince(start_of_year) as Number).floatValue
    
    val String Euro_Heute = String::format("%.2f €",(Solarertrag_Heute * Preis)) // Summe in Euro berechnen
    val String Euro_Woche = String::format("%.2f €",(Solarertrag_Woche * Preis))
    val String Euro_Monat = String::format("%.2f €",(Solarertrag_Monat * Preis))
    val String Euro_Jahr = String::format("%.2f €",(Solarertrag_Jahr * Preis))
    
    Solarertrag_Heute_Item.postUpdate(Solarertrag_Heute.toString + " kWh/" +  Euro_Heute)
    Solarertrag_Woche_Item.postUpdate(Solarertrag_Woche.toString + " kWh/" +  Euro_Woche)
    Solarertrag_Monat_Item.postUpdate(Solarertrag_Monat.toString + " kWh/" +  Euro_Monat)
    Solarertrag_Jahr_Item.postUpdate(Solarertrag_Jahr.toString + " kWh/" +  Euro_Jahr)

end
leider möchte es nicht funktionieren. Es kommt im Log immer die Fehlermeldung.

Code: Alles auswählen

2024-03-30 10:51:21.347 [WARN ] [ab.binding.mqtt.generic.ChannelState] - Command '' from channel 'mqtt:topic:MQTTBroker:Solar:SolarAktuell' not supported by type 'NumberValue': null
2024-03-30 10:51:21.358 [WARN ] [ab.binding.mqtt.generic.ChannelState] - Command '' from channel 'mqtt:topic:MQTTBroker:Solar:SolarHeute' not supported by type 'NumberValue': null
2024-03-30 10:51:21.371 [WARN ] [ab.binding.mqtt.generic.ChannelState] - Command '' from channel 'mqtt:topic:MQTTBroker:Solar:SolarGesamt' not supported by type 'NumberValue': null
Hat jemand einen Tipp für mich was ich anders machen muss ?
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Wechselrichter per MQTT

Beitrag von udo1toni »

Das Shell Script brauchst Du mutmaßlich, um die Wechselrichter Daten überhaupt per mqtt verfügbar zu machen?
Bist Du sicher, dass die verwendeten Items auch persistiert werden?
Für alle Datenpunkte, die weiter in der Vergangenheit liegen als die Inbetriebnahme der Anlage, wirst Du natürlich immer null erhalten, das betrifft also mindestens: den Jahresertrag bis nächstes Jahr - den Monatsertrag bis nächsten Monat - den Wochenertrag bis nächste Woche (immerhin, beides übermorgen)
Der Tagesertrag sollte heute funktionieren, natürlich nur unter der Voraussetzung, dass die Rule nicht vorher mit einer nullPointer Exception abbricht.
Und wieder mal wäre bewiesen, dass es wichtig ist, zunächst zu prüfen, ob ein Ausdruck auch eine Zahl liefert, bevor man versucht, damit zu rechnen...

Außerdem greifst Du auf ein Item zu, welches Du nicht erwähnt hast Solar__Solar_Aktuell vielleicht ist auch da schon was schief gegangen.
Was soll das Wort Item im Namen eines Items? Ein Item ist immer eine Item, egal ob man das nun dran schreibt oder nicht. Es sind also fünf gänzlich unnötige Zeichen...

Deine Fehlermeldung unten widerspricht allerdings auch Deiner Aussage von ganz oben, dass die Channel Daten liefern, da steht ja ganz eindeutig

Code: Alles auswählen

Command '' [...] not supported [...]
Allerdings frage ich mich auch, warum openHAB hier von einem Command spricht, wo es sich doch nach den Channeldefinitionen um Status handelt.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Re: Wechselrichter per MQTT

Beitrag von Snatsch »

Hallo Udo ja das Skript sendet die Daten.
Screenshot (56).png
Solar__Solar_Aktuell ist das was der Wechselrichter im Moment bringt.



Screenshot (57).png
doch die Regel wird abgebrochen.

Code: Alles auswählen

2024-03-30 12:49:53.130 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Solarertrag-1' failed: cannot invoke method public abstract float java.lang.Number.floatValue() on null in Solarertrag
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Wechselrichter per MQTT

Beitrag von udo1toni »

Ja, wie gesagt, das ist zu erwarten. Man sollte immer auf Nullwerte prüfen, bevor man einen Status als Number castet.
:)
Gesetzt den Fall, alle Items sind korrekt...

Code: Alles auswählen

rule "Solarertrag Tag Woche Monat Jahr"
when
    Item Solar_Solar_Gesamt_ changed // changed reicht.
then
   
    val Preis = 0.481 
    val start_of_day   = now.with(LocalTime.MIDNIGHT)                                   // heute, Mitternacht
    val start_of_week  = start_of_day.minusDays(start_of_day.getDayOfWeek.getValue - 1) // Montag
    val start_of_month = start_of_day.withDayOfMonth(1)                                 // Erster Tag des Monats (1)
    val start_of_year  = start_of_day.withDayOfYear(89)                                 // Läuft seit 29.03.2024

    var Float Solarertrag_Heute = 0
    var Float Solarertrag_Woche = 0
    var Float Solarertrag_Monat = 0
    var Float Solarertrag_Jahr  = 0
    if(Solar__Solar_Aktuell.deltaSince(start_of_day)   instanceof Number)
        Solarertrag_Heute = (Solar__Solar_Aktuell.deltaSince(start_of_day)   as Number).floatValue // kWh Delta holen
    if(Solar__Solar_Aktuell.deltaSince(start_of_week)  instanceof Number)
        Solarertrag_Woche = (Solar__Solar_Aktuell.deltaSince(start_of_week)  as Number).floatValue
    if(Solar__Solar_Aktuell.deltaSince(start_of_month) instanceof Number)
        Solarertrag_Monat = (Solar__Solar_Aktuell.deltaSince(start_of_month) as Number).floatValue
    if(Solar__Solar_Aktuell.deltaSince(start_of_year)  instanceof Number)
        Solarertrag_Jahr  = (Solar__Solar_Aktuell.deltaSince(start_of_year)  as Number).floatValue

    val Euro_Heute = String.format("%.2f €",(Solarertrag_Heute * Preis))           // Summe in Euro berechnen
    val Euro_Woche = String.format("%.2f €",(Solarertrag_Woche * Preis))
    val Euro_Monat = String.format("%.2f €",(Solarertrag_Monat * Preis))
    val Euro_Jahr  = String.format("%.2f €",(Solarertrag_Jahr  * Preis))
    
    Solarertrag_Heute_Item.postUpdate(Solarertrag_Heute.toString + " kWh/" +  Euro_Heute)
    Solarertrag_Woche_Item.postUpdate(Solarertrag_Woche.toString + " kWh/" +  Euro_Woche)
    Solarertrag_Monat_Item.postUpdate(Solarertrag_Monat.toString + " kWh/" +  Euro_Monat)
    Solarertrag_Jahr_Item.postUpdate(Solarertrag_Jahr.toString   + " kWh/" +  Euro_Jahr)
end
Folgendes ist noch dazu anzumerken:
Es besteht ein Unterschied zwischen der Definition mittels float und Float. Erstere generiert ein Primitive, letztere ein Objekt. Nur das Objekt kennt die im späteren Verlauf genutzte Methode .toString (war mir vorher gar nicht aufgefallen)
Es ist unüblich, Itemnamen mit einem Unterstrich enden zu lassen. Es mag funktionieren, ich würde mich aber nicht darauf verlassen wollen und damit rechnen, dass es dort früher oder später zu einem weiteren Problem kommt.
Statt lokale Variablen oder Konstanten identisch zum Item zu benennen und in der Folge das Item mit der Endung _Item zu versehen wäre es zielführender, die Variablennamen sinnvoll zu wählen, z.B. statt Solarertrag_Heute fErtrag_Heute (wobei das f für Float steht) oder auch statt Euro_Heute strEuro_Heute (str steht für String).
An vielen Stellen kann und sollte man grundsätzlich auf die starre Typisierung verzichten, openHAB wählt dann selbst den besten Typ aus.

Das wichtigste ist hier aber, auf null-Werte zu testen, bevor Du as Number verwendest.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Re: Wechselrichter per MQTT

Beitrag von Snatsch »

Vielen Dank Udo für deine Hilfe (wie so oft) Jetzt muss ich bis morgen warten bis der Wechselrichter wieder anspringt :) Eine Frage hätte ich aber noch ;) Ich habe ja das Skript im Hintergrund laufen. Ist es Notwendig es alle 5 Sekunden Durchlaufen zu lassen wenn sich der Wechselrichter ja nur alle 6 Minuten aktualisiert und dann habe ich noch gemerkt das das Skript manchmal einfach aufhört zu laufen :roll: Kann man eine Rule schreiben die überprüft z.B alle 2 Minuten ob das Skript läuft und wenn nicht das man es wieder Startet ? Hoffe du verstehst ungefähr was ich meine ;)
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Wechselrichter per MQTT

Beitrag von udo1toni »

Wenn die werte ohnehin nur alle 360 Sekunden aktualisiert werden, kannst Du das Script auch anders gestalten, und zwar lässt Du Schleife und Sleep weg. Dafür legst Du einen cron Job an (in GNU/Linux, nicht in openHAB!) der das Script einfach alle sechs Minuten ausführt. Das hat dann auch den Vorteil, dass Du nicht prüfen musst, ob das Script "noch läuft", es wird einfach ganz normal zyklisch gestartet.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Re: Wechselrichter per MQTT

Beitrag von Snatsch »

Die Rule läuft und gibt auch Werte aus. Aber leider viel zu hohe :( wäre schön wenn es so wäre. Muss in der Rule noch etwas umgerechnet werden ?
Screenshot (58).png
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: Wechselrichter per MQTT

Beitrag von udo1toni »

Ich kenne Deine Datenquelle nicht :)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Re: Wechselrichter per MQTT

Beitrag von Snatsch »

die Daten kommen von MQTT
Screenshot (60).png
und das Item so
Screenshot (59).png
ist das das was du meinst ?
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Snatsch
Beiträge: 367
Registriert: 9. Jan 2021 22:55
Answers: 0

Re: Wechselrichter per MQTT

Beitrag von Snatsch »

Code: Alles auswählen

if(Solar__Solar_Aktuell.deltaSince(start_of_day)   instanceof Number)
        Solarertrag_Heute = (Solar__Solar_Aktuell.deltaSince(start_of_day)   as Number).floatValue // kWh Delta holen
    if(Solar__Solar_Aktuell.deltaSince(start_of_week)  instanceof Number)
        Solarertrag_Woche = (Solar__Solar_Aktuell.deltaSince(start_of_week)  as Number).floatValue
    if(Solar__Solar_Aktuell.deltaSince(start_of_month) instanceof Number)
        Solarertrag_Monat = (Solar__Solar_Aktuell.deltaSince(start_of_month) as Number).floatValue
    if(Solar__Solar_Aktuell.deltaSince(start_of_year)  instanceof Number)
        Solarertrag_Jahr  = (Solar__Solar_Aktuell.deltaSince(start_of_year)  as Number).floatValue
könnte es sein das statt Solar__Solar_Aktuell. Solar_Solar_Gesamt_ hin muss ?
Kann es heute nicht testen da mein Wechselrichter OFF ist
openhab4.1.2 auf Pi 4 im Docker Portainer /Grafana&InfluxDB auf Pi 3 in Docker Portainer/Pi 3 mit Docker zur Datensicherung

Antworten