Seite 1 von 22

Alternative Anbindung von Huawei WR

Verfasst: Do Jun 01, 2023 7:40 pm
von JHC
Moin, moin,

da die Regelzeit mit Huawei WR aufgrund des langsamen Modbus-LAN-Adapters bekanntlich ein Grauß ist, habe ich nach einer anderen Lösung gesucht, die hier seit ein paar Monaten stabil läuft und ich daher gerne mit Euch teilen möchte.

Die Huawei WR spannen ein eigenes WLAN auf, ist ein Client in dieses eingeloggt, kann direkt per ModBus auf den WR zugegriffen werden.
Da das WLAN des WR eine sehr beschränkte Reichweite hat, habe ich als Gateway einen RPI3+ in direkter Umgebung positioniert.
Auf dem RPi sind WLAN und LAN parallel aktiv. Ein Script holt sich über das WLAN die Werte vom WR und pushed diese über LAN in meine openWB.

Das Skript ist für openWB 1.9, die MQTT-Topics müssen für 2.0 angepasst werden.

Code: Alles auswählen

#!/usr/bin/python3
import time
import asyncio
import paho.mqtt.publish as publish
from huawei_solar import HuaweiSolarBridge, register_names as rn, register_values as rv

loop = asyncio.new_event_loop()

# openWB IP:
mqtthost   = "192.168.xxx.xxx"
mqttclient = "PVImporter"

def publish2openWB(mqtttopic, message):
    publish.single(mqtttopic, payload=message, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)

async def huaweiReadValues():

    bridge = await HuaweiSolarBridge.create(host="192.168.200.1", port=6607)

    # Register names
    registers_evu = ['power_meter_active_power']
    registers_wr  = ['input_power', 'accumulated_yield_energy']
    registers_bat = ['storage_state_of_capacity','storage_charge_discharge_power','storage_total_charge','storage_total_discharge']
    registers     =  registers_evu + registers_wr + registers_bat

    # Main Tasks:
    while True:

        if not bridge:
            bridge = await HuaweiSolarBridge.create(host="192.168.200.1", port=6607)
    
        for i in registers:
            try:
                result = await bridge.client.get(i)

                if result[0] is not None:
                    mqtttopic = False

                    if str(i) == "input_power":
                        mqtttopic = "openWB/set/pv/1/W"
                        message = result[0]
                    
                    elif str(i) == "storage_state_of_capacity":
                        mqtttopic = "openWB/set/houseBattery/%Soc"
                        message = result[0]
                        
                    elif str(i) == "storage_charge_discharge_power":
                        mqtttopic = "openWB/set/houseBattery/W"
                        message = result[0]

                    elif str(i) == "accumulated_yield_energy":
                        mqtttopic = "openWB/set/pv/1/WhCounter"
                        message = result[0] * 1000

                    elif str(i) == "storage_total_charge":
                        mqtttopic = "openWB/set/houseBattery/WhImported"
                        message = result[0] * 1000
                        
                    elif str(i) == "storage_total_discharge":
                        mqtttopic = "openWB/set/houseBattery/WhExported"
                        message = result[0] * 1000

                    if mqtttopic is not False:
                        try:
                            publish.single(mqtttopic, payload=message, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)
                        except:
                            pass
            except:
                await bridge.stop()
                bridge = False
                pass

        time.sleep(1)   
    await bridge.stop()

loop.run_until_complete(huaweiReadValues())
In meiner openWB steht PV und Batterie auf MQTT.
Da ich für den EVU ein anderes Smartmeter nutze, müsste hier ggf. das Skript um die entsprechenden MQTT-Topics erweitert werden.

Das Skript starte ich per system.d und erhalte so sekündlich die aktuellen Daten des WR in meiner openWB.

Weitere Informationen:
Viel Erfolg!

Grüße,
Jens

Re: Alternative Anbindung von Huawei WR

Verfasst: Do Jul 27, 2023 7:40 am
von AlexMetzger
Ich habe es nun mit folgendem Script auf der Version2 am laufen und teste aktuell noch ob das alles so weit passt:
Auf dem Pi muss noch die aktuelle Python installiert werden bei mir läuft es mit 3.10
Außerdem muss paho und numpy nachinstalliert werden das geht mit folgenden Befehlen in der Shell:

pip3 install paho-mqtt
sudo pip3 install numpy

Code: Alles auswählen

import time
import asyncio
import paho.mqtt.publish as publish
import numpy as np
import json
from huawei_solar import HuaweiSolarBridge, register_names as rn, register_values as rv

loop = asyncio.new_event_loop()

# openWB IP:
mqtthost = "192.168.178.11"
mqttclient = "PVImporter"

# Dictionary to map register names to MQTT topics
topic_mapping = {
    'input_power': "openWB/set/pv/18/get/power",
    'storage_state_of_capacity': "openWB/set/bat/17/get/soc",
    'grid_accumulated_energy': "openWB/set/counter/16/get/imported",
    'grid_exported_energy': "openWB/set/counter/16/get/exported",
    'storage_charge_discharge_power': "openWB/set/bat/17/get/power",
    'accumulated_yield_energy': "openWB/set/pv/get/exported",
    'daily_yield_energy': "openWB/set/pv/18/get/exported",
    'storage_current_day_charge_capacity': "openWB/set/bat/17/get/imported",
    'storage_current_day_discharge_capacity': "openWB/set/bat/17/get/exported",
    'power_meter_active_power': "openWB/set/counter/16/get/power",
    'grid_frequency': "openWB/set/counter/16/get/frequency",
    'active_grid_power_factor': "openWB/set/counter/16/get/power_factors",
}



def publish2openWB(mqtttopic, message):
    publish.single(mqtttopic, payload=message, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)

async def huaweiReadValues(topic_mapping):
    bridge = await HuaweiSolarBridge.create(host="192.168.200.1", port=6607)

    # Register names
    registers_evu = ['grid_frequency', 'power_meter_active_power', 'active_grid_A_power',
    'active_grid_B_power', 'active_grid_C_power', 'grid_A_voltage', 'grid_B_voltage',
    'grid_C_voltage', 'active_grid_A_current', 'active_grid_B_current', 'active_grid_C_current',
    'grid_exported_energy', 'grid_accumulated_energy', 'active_power', 'grid_voltage', 'active_grid_power_factor']
    registers_wr = ['input_power', 'accumulated_yield_energy', 'active_power', 'daily_yield_energy']
    registers_bat = ['storage_state_of_capacity', 'storage_charge_discharge_power', 'storage_current_day_charge_capacity', 'storage_current_day_discharge_capacity']
    registers = registers_evu + registers_wr + registers_bat

    # Main Tasks:
    while True:
        try:
            if not bridge:
                bridge = await HuaweiSolarBridge.create(host="192.168.200.1", port=6607)

            # Dictionary to store the register values
            register_values = {}

            # Initialize an empty NumPy array for grid currents
            array_currents_grid = np.array([])

            # Initialize an empty NumPy array for grid voltages
            array_voltages_grid = np.array([])
            # Initialize an empty NumPy array for grid voltages
            array_powers_grid = np.array([])
            # Initialize an empty NumPy array for grid voltages
            array_powerfactors_grid = np.array([])

            for i in registers:
                try:
                    result = await bridge.client.get(i)

                    if result[0] is not None and result[0] != 0:
                        mqtttopic = False

                        if str(i) == "input_power":
                            mqtttopic = "openWB/set/pv/18/get/power"
                            message = result[0] * -1

                        elif str(i) == "storage_state_of_capacity":
                            mqtttopic = "openWB/set/bat/17/get/soc"
                            message = result[0]

                        elif str(i) == "grid_accumulated_energy":
                            mqtttopic = "openWB/set/counter/16/get/imported"
                            message = result[0]

                        elif str(i) == "grid_exported_energy":
                            mqtttopic = "openWB/set/counter/16/get/exported"
                            message = result[0]

                        elif str(i) == "storage_charge_discharge_power":
                            mqtttopic = "openWB/set/bat/17/get/power"
                            message = result[0]

                        elif str(i) == "daily_yield_energy":
                            mqtttopic = "openWB/set/pv/18/get/exported"
                            message = result[0] * 1000

                        elif str(i) == "storage_current_day_charge_capacity":
                            mqtttopic = "openWB/set/bat/17/get/imported"
                            message = result[0] * 1000

                        elif str(i) == "storage_current_day_discharge_capacity":
                            mqtttopic = "openWB/set/bat/17/get/exported"
                            message = result[0] * 1000

                        elif str(i) == "power_meter_active_power":
                            mqtttopic = "openWB/set/counter/16/get/power"
                            message = result[0]
                        elif str(i) == "active_grid_power_factor":
                            mqtttopic = "openWB/set/counter/16/get/power_factors"
                            message = result[0]                            

                        elif str(i) == "grid_frequency":
                            mqtttopic = "openWB/set/counter/16/get/frequency"
                            message = result[0]
#                       elif str(i) == "grid_voltage":
#                           mqtttopic = "openWB/counter/16/get/voltages"
#                           message = result[0]
                        # Handle other registers (in this case, the grid currents)
                        # Append numerical grid currents to the array
                        elif i in ['active_grid_A_current', 'active_grid_B_current', 'active_grid_C_current']:
                            mqtttopic = "openWB/set/counter/16/get/currents"
                            array_currents_grid = np.append(array_currents_grid, result[0])

                        # Handle other registers (in this case, the grid voltages)
                        # Append numerical grid voltages to the array
                        elif i in ['grid_A_voltage', 'grid_B_voltage', 'grid_C_voltage']:
                            mqtttopic = "openWB/set/counter/16/get/voltages"
                            array_voltages_grid = np.append(array_voltages_grid, result[0])
                        # Append numerical grid voltages to the array
                        elif i in ['active_grid_A_power', 'active_grid_B_power', 'active_grid_C_power']:
                            mqtttopic = "openWB/set/counter/16/get/powers"
                            array_powers_grid = np.append(array_powers_grid, result[0])
#                        elif i in ['active_grid_power_factor', 'active_grid_power_factor', 'active_grid_power_factor']:
#                            mqtttopic = "openWB/set/counter/16/get/power_factors"
#                            array_powerfactors_grid = np.append(array_powerfactors_grid, result[0])
                        if mqtttopic is not False:
                            register_values[i] = message

                except:
                    await bridge.stop()
                    bridge = False
                    pass

            # Publish the values to their respective topics
            for register, value in register_values.items():
                mqtttopic = topic_mapping.get(register)
                if mqtttopic:
                    try:
                        if register == "active_grid_currents":
                            # Publish the current values as an array
                            publish.single(mqtttopic, payload=value, qos=0, retain=False, hostname=mqtthost,
                                           client_id=mqttclient)
                        if register == "active_grid_voltages":
                            # Publish the voltage values as an array
                            publish.single(mqtttopic, payload=value, qos=0, retain=False, hostname=mqtthost,
                                           client_id=mqttclient)
                        if register == "active_grid_powers":
                            # Publish the voltage values as an array
                            publish.single(mqtttopic, payload=value, qos=0, retain=False, hostname=mqtthost,
                                           client_id=mqttclient)
#                        if register == "active_grid_powerfactors":
 #                           # Publish the voltage values as an array
 #                           publish.single(mqtttopic, payload=value, qos=0, retain=False, hostname=mqtthost,
 #                                          client_id=mqttclient)
                        else:
                            # Publish other values directly
                            publish.single(mqtttopic, payload=value, qos=0, retain=False, hostname=mqtthost,
                                           client_id=mqttclient)
                    except:
                        pass

            # Publish the grid currents as an array
            if array_currents_grid.size > 0:
                mqtttopic = "openWB/set/counter/16/get/currents"
                payload_json = json.dumps(array_currents_grid.tolist())  # Convert to JSON string
                publish.single(mqtttopic, payload=payload_json, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)

            if array_voltages_grid.size > 0:
                mqtttopic = "openWB/set/counter/16/get/voltages"
                payload_json = json.dumps(array_voltages_grid.tolist())  # Convert to JSON string
                publish.single(mqtttopic, payload=payload_json, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)
            if array_powers_grid.size > 0:
                mqtttopic = "openWB/set/counter/16/get/powers"
                payload_json = json.dumps(array_powers_grid.tolist())  # Convert to JSON string
                publish.single(mqtttopic, payload=payload_json, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)
#            if array_powers_grid.size > 0:
#                mqtttopic = "openWB/set/counter/16/get/power_factors"
#                payload_json = json.dumps(array_powerfactors_grid.tolist())  # Convert to JSON string
#                publish.single(mqtttopic, payload=payload_json, qos=0, retain=False, hostname=mqtthost, client_id=mqttclient)


            time.sleep(0.5)

        except KeyboardInterrupt:
            await bridge.stop()
            break

    await bridge.stop()


loop.run_until_complete(huaweiReadValues(topic_mapping))

Re: Alternative Anbindung von Huawei WR

Verfasst: Do Jul 27, 2023 7:24 pm
von hhoefling
Wobei die 16/17/18 etc. An die jeweiligen ID's des Zielsystems angepasst werden müssen.
Je nach Reihenfolge und Anzahl der Installierten Kompenten sind diese Id's in jeder 2.0 Installation anders.
( das ist eins der Probleme die ich mit der 2.0 habe)

Re: Alternative Anbindung von Huawei WR

Verfasst: Fr Jul 28, 2023 6:35 am
von jub
die Zahlen für die jeweiligen mqtt-Topics in der openWB bei "Konfiguration - Geräte und Komponenten - Komponenten" (es dürfte prinzipiell die ID der Komponente sein).

Ich habe mit dem "neutralen" mqtt-Modul herumgespielt - aber seit ein paar Tagen verwende ich die Huawei-Module für Wechselrichter und Zähler und bin zufrieden. Mir fehlen aber noch Beobachtungen von früher, ob es dauerhaft stabil läuft, bzw unter welchen Voraussetzungen.
Zwei Sachen: ich habe den Huawei-Dongle von der V100 auf V200..07 aktualisiert, aber auch openWB2 aktuell gehalten. Was auf jeden Fall Schwierigkeiten beim Auslesen macht, ist, wenn parallel ein zweiter Lesevorgang läuft (das war bei mir mit dem mqtt über node-red).


EDIT: gerade habe ich Fusionsolar aufgemacht, schon gibts den ersten Fehler vom Huawei-Modul...

Re: Alternative Anbindung von Huawei WR

Verfasst: Sa Jul 29, 2023 10:55 am
von AlexMetzger
Ich weiß noch nicht genau wieso aber jetzt lief es 1 Tag komplett problemlos durch und heute morgen musste ich noch zwei werte invertieren weil die auf einmal falsch rum angezeigt wurden.

Re: Alternative Anbindung von Huawei WR

Verfasst: Fr Aug 04, 2023 2:42 pm
von AlexMetzger
Hallo Zusammen,
ich hab mich mal daran versucht eine praxistaugliche Lösung zu erstellen für das Problem das in der Version 2 der Huawei Wechselrichter mit der OpenWB immer wieder zu Fehlern führt.

Die Kurzfassung: es gibt ein fertiges Image das muss auf eine SD karte, die kommt in einen Raspberry Pi. Der wird mit LAN verbunden und über ein Webinterface dann ganz unkompliziert das WLAN des Huawei Sun2000 Wechselrichters abgegriffen und die IP Adresse der Open eingetragen.
In OpenWB wird dann statt der Zähleranbinung über das Huawei Modul die Komponenten über MQTT hinzugefügt.

Hier hab Ichs in einem Video gezeigt und erklärt: https://youtu.be/nb7wcyGZLEE
Hier das ganze noch in Schriftform und der Link zum Image: https://lebensraum-wohnraum.de/openwb-k ... -sun-2000/

Aktuell hab ich immer mal wieder einen einfrierenden Wert der Speicherleistung, so wie es aussieht immer dann wenn der Speicher komplett voll ist. Meistens behebt es sich von selbst wenn ein Verbraucher mit etwas mehr Leistung aus dem Speicher zieht oder der Pi mal neugestartet wird. Sobald ich eine Lösung habe werde ich diese bereitstellen.

Re: Alternative Anbindung von Huawei WR

Verfasst: Fr Aug 04, 2023 6:10 pm
von aiole
Großer Respekt Alex!
Das taugt sicher als Alternativlösung. Auch eine super Doku + Video + sogar Image!
Da das Problem an der Wurzel gelöst wird, kann man es nur empfehlen - Danke!

Re: Alternative Anbindung von Huawei WR

Verfasst: Fr Aug 04, 2023 10:15 pm
von jub
Schön!

Ich habe es (hoffentlich) gerade geschafft, per node-red auf einem raspi (bzw genauer einem revpi) die Register per modbus-tcp über LAN (Dongle) auzulesen und per mqtt an die openwb zu übertragen. Morgen wird sich zeigen, ob die Berechnungen stimmen - bisher hatte ich Probleme mit dem Hausverbrauch (weil nicht plausibel/negativ).
Abrufintervall habe ich aktuell bei 7 Sekunden und rufe die Register in 2 Gruppen ab - das dürfte schneller und verlässlicher gehen, als einzelne Register.

Dongle Firmware ist die v200..007, Wechselrichter (SUN2000-36KTL-M3) hat die v100..PC125.
Als Import und Export-Werte habe ich die Register 37119 und 37121 genommen. Vermutlich wegen der neuen Dongle-Firmware kann man auch mit der Modbus-ID 100 Werte vom Dongle auslesen, aber der Wechsel, wenn die ID 1 auch gelesen wird - so glaube ich - führt zu einem Stop der Kommunikation, einzeln gehts zumindest bei meinen Tests.


Alex, läuft das bei Dir wirklich über wlan direkt vom Wechselricher-Wlan?

Re: Alternative Anbindung von Huawei WR

Verfasst: Fr Aug 04, 2023 11:18 pm
von aiole
Bin zwar nicht Alex, kenne aber die Funktion - ja -> Der WLAN-Hotspot des Huawei liefert die Daten und dann wird auf LAN umgesetzt.

Alex hat hier alles perfekt dokumentiert:
https://youtu.be/nb7wcyGZLEE
https://lebensraum-wohnraum.de/openwb-k ... -sun-2000/

Re: Alternative Anbindung von Huawei WR

Verfasst: Sa Aug 05, 2023 9:44 am
von AlexMetzger
das Problem mit den nicht plausiblen hauswerten könnte davon kommen wenn die Werte nicht das korrekte Vorzeichen haben also + und - vertauscht ist.

Ich hab auch mal den Stromverbrauch gemessen vom Pi Zero W der braucht im betrieb ca. 1W. Was aber mit meinem Unifi 8 Port PoE Switch bisher noch nicht funktioniert ist die PoE Variante, ich weiß noch nicht ob es am Switch liegt oder am POE HAT da werd ich noch bisschen rumprobieren.