Sungrow SH10.RT Modbus integration

Der Zugriff über das WebUi funktioniert aber nur für den SG5.0RT. Für den SH8.0RT funktioniert es nur sporadisch. Meistens bekomme ich da einen Netzwerkfehler angezeigt.

Was wirklich komisch ist, ist dass wenn ich in der secrets.yaml als erste IP die vom SH8.0RT angebe und als zweite die vom SG5.0RT, dann bekomme ich für alle Werte die des SH8.0RT. Selbst für den device type steht zwei mal SH8.0RT drin.

EDIT:
Mittlerweile bekomme ich teilweise auch die Werte des SG5.0RT. Manche Werte bekomme ich aber immer noch nicht. Z.B. Daily & Total PV Generation

Das IP Problem hatte ich nicht, allerdings benutze ich auch den Modbus Stecker an dem SH und den WiNet für die Wallbox. Das würde ich dir auch empfehlen, da der Modbus Stecker viel mehr Abfragen verträgt.
Warum das IP Problem besteht kann ich dir nicht ohne Config Code sagen

- name: SG-20 WiNet Inverter temperature
  unique_id: sg_20_winet_inverter_temperature
  device_address: 1
  address: 5007 # reg 5008
  input_type: input
  data_type: int16
  precision: 1
  unit_of_measurement: °C
  device_class: Temperature
  state_class: measurement
  scale: 0.1
  scan_interval: 30
- name: SG-20 WiNet MPPT1 voltage
  unique_id: sg_20_winet_mppt1_voltage
  device_address: 1
  address: 5010 # reg 5011
  input_type: input
  data_type: uint16
  precision: 1
  unit_of_measurement: V
  device_class: Voltage
  state_class: measurement
  scale: 0.1
  scan_interval: 10
- name: SG-20 WiNet MPPT1 current
  unique_id: sg_20_winet_mppt1_current
  device_address: 1
  address: 5011 # reg 5012
  input_type: input
  data_type: uint16
  precision: 2
  unit_of_measurement: A
  device_class: Current
  state_class: measurement
  scale: 0.1
  scan_interval: 10
- name: SG-20 WiNet MPPT2 voltage
  unique_id: sg_20_winet_mppt2_voltage
  device_address: 1
  address: 5012 # reg 5013
  input_type: input
  data_type: uint16
  precision: 1
  unit_of_measurement: V
  device_class: Voltage
  state_class: measurement
  scale: 0.1
  scan_interval: 10
- name: SG-20 WiNet MPPT2 current
  unique_id: sg_20_winet_mppt2_current
  device_address: 1
  address: 5013 # reg 5014
  input_type: input
  data_type: uint16
  precision: 2
  unit_of_measurement: A
  device_class: Current
  state_class: measurement
  scale: 0.1
  scan_interval: 10
- name: SG-20 WiNet Total DC power
  unique_id: sg_20_winet_total_dc_power
  device_address: 1
  address: 5016 # reg 5017
  input_type: input
  data_type: uint32
  swap: word
  precision: 0
  unit_of_measurement: W
  device_class: power
  state_class: measurement
  scale: 1
  scan_interval: 10
- name: SG-20 WiNet Grid frequency
  unique_id: sg_20_winet_grid_frequency
  device_address: 1
  address: 5035 # reg 5036
  input_type: input
  data_type: uint16
  precision: 2
  unit_of_measurement: "Hz"
  device_class: frequency
  state_class: measurement
  scale: 0.1
  scan_interval: 30
- name: SG-20 WiNet Reactive power
  unique_id: sg_20_winet_reactive_power
  device_address: 1
  address: 5032 # reg 5033
  input_type: input
  data_type: int32
  swap: word
  precision: 0
  unit_of_measurement: W
  device_class: power
  state_class: measurement
  scale: 1
  scan_interval: 30
- name: SG-20 WiNet Power factor
  unique_id: sg_20_winet_power_factor
  device_address: 1
  address: 5034 # reg 5035
  input_type: input
  data_type: int16
  precision: 3
  unit_of_measurement: "%"
  device_class: power_factor
  state_class: measurement
  scale: 0.001
  scan_interval: 30
- name: SG-20 WiNet Meter active power raw
  unique_id: sg_20_winet_meter_active_power_raw
  device_address: 1
  address: 5600 # reg 5601
  input_type: input
  data_type: int32
  swap: word
  precision: 0
  unit_of_measurement: W
  device_class: power
  state_class: measurement
  scale: 1
  scan_interval: 10
- name: SG-20 WiNet BDC rated power
  unique_id: sg_20_winet_bdc_rated_power
  device_address: 1
  address: 5627 # reg 5628
  input_type: input
  data_type: uint16
  unit_of_measurement: "W"
  device_class: power
  state_class: measurement
  scale: 100
  scan_interval: 300

Das sind glaube ich alle Register für den SG die funktionieren. Der Rest hat bei mir auch keine Inhalte.

Beim SH verwende ich auch den Modbus Stecker. Aber der SG5.0RT hat leider gar keinen. Dann lässt sich da wahrscheinlich nicht viel machen.

Ich versuche vielleicht einfach mal den fehlenden Wert für die erzeugte Energie über ein Integral von der Leistung selbst zu berechnen. Mal schauen wie gut das klappt.

Vielen Dank für die ganzen Antworten.

Ja der hat leider keinen.

Ich habe da noch nicht alles verstanden, aber mit diesem Addon kommst du an so einige Daten: GitHub - MickMake/GoSungrow: GoLang implementation to access the iSolarCloud API updated by SunGrow inverters.
Wenn du dabei einen Error bekommst, dann folge der Anleitung hier: Compiling GoSungrow · GitHub

Hallo Stefan ,

Wie sieht deine secrets yaml aus ?
Und die Integration yaml von dem 2 WR ?

SG über WiNet S über lan an Router , ist richtig …!

De SG liefert nicht viele werte , aber die reichen für Auswertung…

Wie hast du die Anlage konfiguriert?

Mit freundlichen Grüßen

Hallo Artur,

so sieht meine secrets.yaml aus:

# first inverter SH8.0RT
sungrow_modbus_host_ip: 192.168.178.55 # TODO update with the IP of your inverter. No default. Check your router.
sungrow_modbus_port: 502 # TODO update with the Modbus port of your inverter. Default is '502'
sungrow_modbus_slave: 1 #TODO update with the slave address of your inverter. Default is '1'
# second Inverter SG5.0RT
sungrow2_modbus_host_ip: 192.168.178.56 # TODO update with the IP of your inverter. No default. Check your router.
sungrow2_modbus_port: 502 # TODO update with the Modbus port of your inverter. Default is '502'
sungrow2_modbus_slave: 1 #TODO update with the slave address of your inverter. Default is '1'

Hier ein Ausschnitt aus der integration yaml vom 2. WR:

modbus:
  - name: SungrowSHx 2
    type: tcp
    host: !secret sungrow2_modbus_host_ip
    port: !secret sungrow2_modbus_port
    sensors:
      - name: Sungrow device type code2
        unique_id: sg_dev_code2
        slave: !secret sungrow2_modbus_slave
        address: 4999 # reg 5000
        input_type: input
        data_type: uint16
        scan_interval: 600

      - name: Daily PV generation & battery discharge2
        unique_id: sg_daily_pv_gen_battery_discharge2
        slave: !secret sungrow2_modbus_slave
        address: 5002 # reg 5003
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: kWh
        device_class: energy
        state_class: total_increasing
        scale: 0.1
        scan_interval: 600

Viele Werte von dem SG bekomme ich auch. Aber nicht alle. Insbesondere Total PV generation2 fehlt mir um das Energy Dashboard ordentlich zum Laufen zu bekommen.

Hier noch der Abschnitt dazu:

      - name: Total PV generation2
        unique_id: sg_total_pv_generation2
        slave: !secret sungrow2_modbus_slave
        address: 13002 # reg 13003
        input_type: input
        data_type: uint32
        swap: word
        precision: 1
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
        scale: 0.1
        scan_interval: 600

Viele Grüße
Stefan

Hallo Stefan ,

Ja ich meine das ist ein der Fehler in der Adresse.

Bei meiner Anlage , SH 10 RT und SG 5 ORT .
Hab ich als 2 getrennte Anlagen erstellt.

Dem entsprechend , hab ich die secrets yaml anders erstellt!
Ich versuche dir die Yaml zur Verfügung zu stellen !

Weist du wie das geht , muss ich die Datei als Text Speicher ?

Hallo Artur,

einfach einen neuen Kommentar erstellen, STRG + E und dann den kopierten code einfügen.

# Home Assistant Sungrow inverter integration
# https://github.com/mkaiser/Sungrow-SHx-Inverter-Modbus-Home-Assistant
# by Martin Kaiser
# last update: 2023-09-28

modbus:
  - name: WR2_Sungrow_SG5.0RT
    type: tcp
    host: !secret sungrow_wr2_modbus_host_ip
    port: !secret sungrow_wr2_modbus_port
    retries: 10

    sensors:
      - name: WR2_Sungrow device type code
        unique_id: wr2_dev_code
        slave: !secret sungrow_wr2_modbus_slave
        address: 4999 # reg 5000
        input_type: input
        data_type: uint16
        scan_interval: 600

      - name: WR2_Inverter temperature
        unique_id: wr2_inverter_temperature
        slave: !secret sungrow_wr2_modbus_slave
        address: 5007 # reg 5008
        input_type: input
        data_type: int16
        precision: 1
        unit_of_measurement: °C
        device_class: Temperature
        scale: 0.1
        scan_interval: 10

      - name: WR2_MPPT1 voltage
        unique_id: wr2_mppt1_voltage
        slave: !secret sungrow_wr2_modbus_slave
        address: 5010 # reg 5011
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: V
        device_class: Voltage
        scale: 0.1
        scan_interval: 10

      - name: WR2_MPPT1 current
        unique_id: wr2_mppt1_current
        slave: !secret sungrow_wr2_modbus_slave
        address: 5011 # reg 5012
        input_type: input
        data_type: uint16
        precision: 2
        unit_of_measurement: A
        device_class: Current
        scale: 0.1
        scan_interval: 10

      - name: WR2_MPPT2 voltage
        unique_id: wr2_mppt2_voltage
        slave: !secret sungrow_wr2_modbus_slave
        address: 5012 # reg 5013
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: V
        device_class: Voltage
        scale: 0.1
        scan_interval: 10

      - name: WR2_MPPT2 current
        unique_id: wr2_mppt2_current
        slave: !secret sungrow_wr2_modbus_slave
        address: 5013 # reg 5014
        input_type: input
        data_type: uint16
        precision: 2
        unit_of_measurement: A
        device_class: Current
        scale: 0.1
        scan_interval: 10

      - name: WR2_Total DC power
        unique_id: wr2_total_dc_power
        slave: !secret sungrow_wr2_modbus_slave
        address: 5016 # reg 5017
        input_type: input
        data_type: uint32
        swap: word
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: WR2_Grid frequency
        unique_id: wr2_grid_frequency
        slave: !secret sungrow_wr2_modbus_slave
        address: 5035 # reg 5036
        input_type: input
        data_type: uint16
        precision: 2
        unit_of_measurement: "Hz"
        device_class: frequency
        state_class: measurement
        scale: 0.1
        scan_interval: 10

      - name: WR2_Reactive power
        unique_id: wr2_reactive_power
        slave: !secret sungrow_wr2_modbus_slave
        address: 5032 # reg 5033
        input_type: input
        data_type: int32
        swap: word
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: WR2_Power factor
        unique_id: wr2_power_factor
        slave: !secret sungrow_wr2_modbus_slave
        address: 5034 # reg 5035
        input_type: input
        data_type: int16
        precision: 3
        unit_of_measurement: "%"
        device_class: power_factor
        state_class: measurement
        scale: 0.001
        scan_interval: 10

      - name: WR2_Meter active power raw
        unique_id: wr2_meter_active_power_raw
        slave: !secret sungrow_wr2_modbus_slave
        address: 5600 # reg 5601
        input_type: input
        data_type: int32
        swap: word
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: WR2_BDC rated power
        unique_id: wr2_bdc_rated_power
        slave: !secret sungrow_wr2_modbus_slave
        address: 5627 # reg 5628
        input_type: input
        data_type: uint16
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        scale: 100
        scan_interval: 600

      - name: WR2_System state
        unique_id: wr2_system_state
        slave: !secret sungrow_wr2_modbus_slave
        address: 5037 # reg 5038
        input_type: input
        data_type: uint16
        precision: 0
        scale: 1
        scan_interval: 10

      - name: WR2_Running state
        unique_id: wr2_running_state
        slave: !secret sungrow_wr2_modbus_slave
        address: 5038 # reg 5039
        input_type: input
        data_type: uint16
        precision: 0
        scale: 1
        scan_interval: 10

      - name: WR2_Daily PV generation
        unique_id: wr2_daily_pv_generation
        slave: !secret sungrow_wr2_modbus_slave
        address: 5002 # reg 5003
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: kWh
        device_class: energy
        state_class: total_increasing
        scale: 0.1
        scan_interval: 600

      - name: WR2_Total PV generation
        unique_id: wr2_total_pv_generation
        slave: !secret sungrow_wr2_modbus_slave
        address: 5003 # reg 5004
        input_type: input
        data_type: uint32
        swap: word
        precision: 1
        unit_of_measurement: kWh
        device_class: energy
        state_class: total

        scan_interval: 600


# 'virtual' template sensors for better readability
template:
  - binary_sensor:
      - name: WR2_PV generating
        unique_id: wr2_pv_generating
        availability: >-
          {{states('sensor.wr2_running_state')|is_number or 
            states('sensor.wr2_total_dc_power')|is_number
          }}
        delay_on:
          seconds: 60
        state: >-
          {% if states('sensor.wr2_running_state')|is_number %}
            {# use available sensor running_state #}
            {{ states('sensor.wr2_running_state')|int(default=0)|bitwise_and(0x1) > 0 }}
          {% else %} 
            {# workaround for SH*RS inverters without working running_state #}
            {% if states('sensor.wr2_total_dc_power')|int > 0 %}
              1
            {% else %} 
              0 
            {% endif %}
          {% endif %}


  - sensor:
      - name: WR2_MPPT1 power
        unique_id: wr2_mppt1_power
        unit_of_measurement: W
        device_class: power
        availability: "{{states('sensor.wr2_mppt1_voltage')|is_number and states('sensor.wr2_mppt1_current')|is_number }}"
        state: "{{ (states('sensor.wr2_mppt1_voltage') | float * states('sensor.wr2_mppt1_current') | float) |int }}"

      - name: WR2_MPPT2 power
        unique_id: wr2_mppt2_power
        unit_of_measurement: W
        device_class: power
        availability: "{{states('sensor.wr2_mppt2_voltage')|is_number and states('sensor.wr2_mppt2_current')|is_number }}"
        state: "{{ (states('sensor.wr2_mppt2_voltage') | float * states('sensor.wr2_mppt2_current') | float) |int }}"

      - name: WR2_Sungrow inverter state
        unique_id: wr2_inverter_state
        state: >-
          {% if ((states('sensor.wr2_system_state') | int(default=0)) == 0x8000) %}
            Stop
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1400) %}
            Standby
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1200) %}
            Initial Standby
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1600) %}
            Startup
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x0) %}
            Running
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x5500) %}
            Fault
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1500) %}
            Emergency Stop
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1200) %}
            Initial standby
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x9100) %}
            Alarm run
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x8100) %}
            Derating run
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x8200) %}
            Dispatch run
          {% elif ((states('sensor.wr2_system_state') | int(default=0)) == 0x1300) %}
            Key stop
          {% else %}
            Unknown - should not see me!
          {% endif %}

      - name: WR2_Sungrow device type
        unique_id: wr2_device_type
        state: >-
          {% if ((states('sensor.wr2_sungrow_device_type_code') | int(default=0))  == 0x243D) %}
            SG3.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x243E) %}
            SG4.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2430) %}
            SG5.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2431) %}
            SG6.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x243C) %}
            SG7.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2432) %}
            SG8.0RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2433) %}
            SG10RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2434) %}
            SG12RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2435) %}
            SG15RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2436) %}
            SG17RT
          {% elif ((states('sensor.wr2_sungrow_device_type_code') | int(default=0)) == 0x2437) %}
            SG20RT
          {% else %}
            Unknown device code!
          {% endif %}

input_select:
  wr2_set_inverter_run_mode:
    name: WR2_Inverter mode
    options:
      - "Enabled"
      - "Shutdown"

# Automations: Write modbus registers on input changes via GUI
# note: If you change a value by the sliders, it will take up to 60 seconds until the state variables are updated
# Unfortunately, I could not find a way to "force update" modbus registers, yet...
automation:
  - id: "automation_wr2_sungrow_inverter_state"
    alias: "sungrow wr2 inverter state"
    description: "Enables/ stops the inverter"
    trigger:
      - platform: state
        entity_id:
          - input_select.wr2_set_inverter_run_mode
    condition: []
    variables:
      sg_start: 0xCF
      sg_stop: 0xCE
    action:
      - service: modbus.write_register
        data_template:
          hub: WR2_Sungrow_SG6.0RT
          slave: !secret sungrow_wr2_modbus_slave
          address: 12999 # reg 13000
          value: >
            {% if is_state('input_select.wr2_set_inverter_run_mode', 'Enabled') %}
            {{sg_start}}
            {% else %}
            {{sg_stop}}
            {% endif %}
    mode: single

  - id: "automation_wr2_sungrow_inverter_state_input_selector_update"
    alias: "sungrow wr2 inverter enable/ stop input selector update"
    description: "Updates enable/ stops input selector"
    trigger:
      - platform: state
        entity_id:
          - sensor.wr2_system_state
    condition: []
    action:
      - service: input_select.select_option
        target:
          entity_id: input_select.wr2_set_inverter_run_mode
        data:
          option: >
            {% if is_state('sensor.wr2_sungrow_inverter_state', 'Stop') %}
            "Shutdown"
            {% else %}
            "Enabled"
            {% endif %}
    mode: single

Hallo Zusammen,
ich kämpfe gerade mit einer Sache.
Ich würde gerne über HA die Backup-Funktion aktivieren bzw. deaktivieren können.
Dazu gibt es aber keine entität bei M.Kaiser
Und welches Register das ist, finde ich auch nirgends.
Hat das jemand schon mal gebastelt?

Hello everyone,
I’m currently struggling with something.
I would like to be able to activate or deactivate the backup function via HA.
But there is no entity for this in M.Kaiser
And I can’t find anywhere which register this is.
Has anyone ever tinkered with this?

Has somebody two SH10RT-V112 running as master/slave?
I only seem to be able to read out the master.

Hi Mkai

I am totally fresh here and know near to nothing… trying to install the modbusTCP2MQTT to connect mysungrow inverter… but getting fail notification:

The command ‘/bin/ash -o pipefail -c pip install --upgrade pycryptodomex==3.11.0 --no-cache-dir -r requirements.txt’ returned a non-zero code: 1

what am I doing wrong?

Hi, I am wondering if you managed to get the SH10RS working.

I connected it to the single LAN port (WiNet-S2) port, as per the comments in this thread. I can access the WiNet-S2 portal page (shows live data for the device, via the same IP address in the below error - can add a screenshot of the page).

Note, I did try the two other COM ports, but they never produced a network connection of any sort - tried a few different ways to get a connection via them

I’ve followed the configuartion directions for this integration and am receiving an error:

Pymodbus: SungrowSHx: Error: device: 1 address: 4999 -> Modbus Error: [Connection] Not connected[AsyncModbusTcpClient 192.168.86.140:502]

Did you have to make additional adjustments to get the Modbus to feed the data into Hass?

Hallo Achim,
bei mir hat der Installateur die Backup-Funktion aktiviert.
Allerdings meine ich, dass es über die icloudsolar-App auch gehen müsste, wenn du alle Berechtigungen erhalten hast.
Nach einmaliger Aktivierung habe ich die Funktion nicht wieder deaktiviert und passe nur die Backup-Reserve über HA der Wetterlage entsprechend an. Daher war die Aktivierung / Deaktivierung über HA bislang nicht notwendig.
VG Ralph

Hi,

I am working on a Sungrow Sh10RT inverter and I am finding that even when Self-consume mode is triggered the inverter is not supplying current to the house. I am not sure if it is a problem with the integration or the inverter? To keep things simple I have created a script that sends these modbus commands directly to the inverter, it matches this integration. Is there anything else I should be doing to trigger the inverter to go into Self-Consume mode?

alias: "SMART MOTION: Self-consumption mode battery"
sequence:
  - service: modbus.write_register
    data:
      hub: SungrowSHx
      slave: 1
      address: 13050
      value: 204
    alias: Set Stop (default)
  - service: modbus.write_register
    data:
      hub: SungrowSHx
      slave: 1
      address: 13049
      value: 0
    alias: Set EMS Mode Self-consumption mode (default)

Does anyone know how to get the scan_interval in practice down below 5 seconds?

Did you get readings to work with RS485?

I am doing the same thing, same inverter, seems to work fine for me:

    sequence:
      - service: modbus.write_register
        metadata: {}
        data:
          hub: SungrowSHx
          address: 13049
          slave: 1
          value: 0
      - service: modbus.write_register
        metadata: {}
        data:
          hub: SungrowSHx
          address: 13050
          slave: 1
          value: 204

Hallo,
kann es sein das der SH10RT nur von einem Gerät Modbus Abfragen annimmt?
Ich habe schon ein anderes Projekt laufen das den Sungrow abfragt über Modbus.
Jetzt wollte ich über Home Assistent zusätzlich die Werte abgreifen, da kommt aber
2024-06-21 08:55:11.582 ERROR (MainThread) [homeassistant.components.modbus.modbus] Pymodbus: SungrowSHx: Error: device: 1 address: 4999 → Modbus Error: [Connection] Not connected[AsyncModbusTcpClient 192.168.2.211:502]

Hi, new to the forum, please go easy on me.

I am after the method to change parameters on the SH10RT to govern export management, via HA.

I have seen posts here from @mvandersteen, and from what I can read - it looks like you have cracked it, or have a line on it.

FYI - I have the SH10RT, with 38kw of storage, have just gone wholesale on the grid provider, so having tight, automated control on when we should and should not export is now a big deal. The modbus/TCP integration is on sing, I can see all of the data from the inverter, but I have not sussed out how to change it. Specifically the parameters that govern the export management.

Appreciate people’s patience with this specific query, and will be grateful for any assistance.

Cheers !