I am new to Home Assistant and created my .yaml Modbus integration for my Sungrow SGH10.RT. Most of the stuff works now, after I asked the support to send me a modbus register map (which they really did after 3 days yeah).
In the datasheet there are some differences between sungrow models. But most of the registers are the same, so it should also work with SG* models
btw. I donāt know yet, where I should paste code like this in this forum. This is why I hijack this thread, as it was the only thread the search function returned searching for āsungrowā
So here is my current code. Feel free to ask / criticize
modbus:
- name: SungrowSH10 adapt this!
type: tcp
host: 192.168.178.20 adapt this!
port: 502 adapt this!
# retry_on_empty : true
# retries: 10
# close_comm_on_error: true
#delay: 5
#timeout: 5
sensors:
- name: Daily PV generation & battery discharge
slave: 100 adapt this and following slave addresses!
address: 5002
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Total PV generation & battery discharge
slave: 100
address: 5003
input_type: input
count: 2
data_type: uint32
swap: word
unit_of_measurement: kWh
precision: 1
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Inverter temperature
slave: 100
address: 5007
input_type: input
count: 1
data_type: int16
precision: 1
unit_of_measurement: Ā°C
device_class: Temperature
scale: 0.1
scan_interval: 10
- name: MPPT1 voltage
slave: 100
address: 5010
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: V
device_class: Voltage
scale: 0.1
scan_interval: 10
- name: MPPT1 current
slave: 100
address: 5011
input_type: input
count: 1
data_type: uint16
swap: word
precision: 2
unit_of_measurement: A
device_class: Current
scale: 0.1
scan_interval: 10
- name: MPPT2 voltage
slave: 100
address: 5012
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: V
device_class: Voltage
scale: 0.1
scan_interval: 10
- name: MPPT2 current
slave: 100
address: 5013
input_type: input
count: 1
data_type: uint16
swap: word
precision: 2
unit_of_measurement: A
device_class: Current
scale: 0.1
scan_interval: 10
- name: Total DC power
slave: 100
address: 5016
input_type: input
count: 2
data_type: uint32
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Reactive power
slave: 100
address: 5032
input_type: input
count: 2
data_type: int32
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Power factor
slave: 100
address: 5034
input_type: input
count: 1
data_type: int16
swap: word
precision: 3
unit_of_measurement: "%"
device_class: power_factor
state_class: measurement
scale: 0.001
scan_interval: 10
- name: System state
slave: 100
address: 12999
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
scale: 1
scan_interval: 10
- name: Running state
slave: 100
address: 13000
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
scale: 1
scan_interval: 10
- name: Daily PV generation
slave: 100
address: 13001
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total PV generation
slave: 100
address: 13002
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Daily exported energy from PV
slave: 100
address: 13004
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total exported energy from PV
slave: 100
address: 13005
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Load power
slave: 100
address: 13007
input_type: input
count: 2
data_type: int32
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Export power
slave: 100
address: 13009
input_type: input
count: 2
data_type: int32
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Daily battery charge from PV
slave: 100
address: 13011
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total battery charge from PV
slave: 100
address: 13012
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Daily direct energy consumption
slave: 100
address: 13016
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total direct energy consumption
slave: 100
address: 13017
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Battery voltage
slave: 100
address: 13019
input_type: input
count: 1
data_type: uint16
swap: word
precision: 0
unit_of_measurement: V
device_class: Voltage
scale: 0.1
scan_interval: 10
- name: Battery current
slave: 100
address: 13020
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: A
device_class: Current
scale: 0.1
scan_interval: 10
- name: Battery power
slave: 100
address: 13021
input_type: input
count: 1
data_type: uint16
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Battery level
slave: 100
address: 13022
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: "%"
device_class: battery
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Battery state of health
slave: 100
address: 13023
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: "%"
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Battery temperature
slave: 100
address: 13024
input_type: input
count: 1
data_type: int16
precision: 1
unit_of_measurement: Ā°C
device_class: Temperature
scale: 0.1
scan_interval: 10
- name: Daily battery discharge
slave: 100
address: 13025
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total battery discharge
slave: 100
address: 13026
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Grid state
slave: 100
address: 13029
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
scale: 0.1
scan_interval: 10
- name: Total active power
slave: 100
address: 13033
input_type: input
count: 2
data_type: int32
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Daily imported energy
slave: 100
address: 13035
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total imported energy
slave: 100
address: 13036
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Daily battery charge
slave: 100
address: 13039
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total battery charge
slave: 100
address: 13040
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Daily exported energy
slave: 100
address: 13044
input_type: input
count: 1
data_type: uint16
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: measurement
scale: 0.1
scan_interval: 10
- name: Total exported energy
slave: 100
address: 13045
input_type: input
count: 2
data_type: uint32
swap: word
precision: 1
unit_of_measurement: kWh
device_class: energy
state_class: total_increasing
scale: 0.1
scan_interval: 10
- name: Charge discharge power
slave: 100
address: 13051
input_type: input
count: 1
data_type: int16
swap: word
precision: 0
unit_of_measurement: W
device_class: power
state_class: measurement
scale: 1
scan_interval: 10
- name: Battery current
slave: 100
address: 13108
input_type: input
count: 1
data_type: uint16
swap: word
unit_of_measurement: A
device_class: Current
precision: 0
scale: 1
scan_interval: 10
- name: Battery voltage
slave: 100
address: 13109
input_type: input
count: 1
data_type: uint16
swap: word
unit_of_measurement: V
device_class: Voltage
precision: 0
scale: 1
scan_interval: 10
binary_sensor:
- platform: template
sensors:
battery_charging:
friendly_name: "Battery charging"
value_template: "{{ states('sensor.running_state')|int|bitwise_and(1) > 0 }}"
battery_discharging:
friendly_name: "Battery discharging"
value_template: "{{ states('sensor.running_state')|int|bitwise_and(2) > 0 }}"
exporting_power:
friendly_name: "Exporting power"
value_template: "{{ states('sensor.running_state')|int|bitwise_and(4) > 0 }}"
importing_power:
friendly_name: "Importing power"
value_template: "{{ states('sensor.running_state')|int|bitwise_and(5) > 0 }}"
Have have put together a solution for Sungrow Hybrid Inverters at the moment refer to the link below to see if your inverter is supported.
Those that are after the modbus register addresses (official) have uploaded the pdf for String & Hybrid inverters to the python module site which has been developed as part of this solution (SungrowInverter Ā· PyPI).
You will be able to see what String Inverters can be supported once Iāve completed development, at that site. Let me know if this interests you, otherwise i wont bother as I donāt require it.
Please be aware if you use this at present there is a possibility sensor names will be changed, Iāll try limit that as much as possible though.
Let me know how you go. if you are unsure of installing custom integrations in into ~/config/custom_components then this solution may not be for you. Iāll see how time goes for a proper Hass.io solution as thats what i use these days as well, need to teach myself how that works though.
This looks great, @mvandersteen, thanks for your work. I have installed the component, but have an SG5K-D inverter (no battery) and it doesnāt sound like youāve added support for this yet. I havenāt done much work on modbus etc in the past, but if thereās code youād like me to test for this model, let me know.
@simon4 iāll make the change to suite SGxx inverter soon seeing as there is a need.
@mkai Iāll check your solution as well there maybe something Iāve missed, I have noticed that all those inverters you have mentioned do support the same set of registers, some inverters (like mine SH5K) just donāt record anything to all of them, also I got a lot of fixing up to do yet. Any help or advise will be taken
@mvandersteen Have you looked in to not only reading values, but also setting values?
Iām about to install a SH10RT with panels and battery, and in wintertime with the current electricity prices it would be very nice to be able to set the charging mode to have the battery charge when the price is low.
@jamie.carlyle Iām having a look at this today, iāll see where I get, most of the work is to marry up the register-code names for both inverter types which i didnāt do at the start which was silly.
@Dali01 I have considered this and probably will at some point because my clock is always out crossing over day light savings, and I have considering the same thing. Fo rexample what i would like to do is here in Melbourne Australia, peak electricity is between 3pm and 9pm (for my retailer anyway) and in middle of winter when not getting a full charge from solar would like to charge the battery before 3pm. So at some point I will investigate. I havenāt looked into what that means yet though, happy to accept any info on how to do this. I would imagine its just sending a value to the relevant register with different modbus command and possibly slave address though.
Iām based in Melbourne AU also, just had my system installed - Sungrow SH5.0RS with SBR096 battery.
I tried your integration but the script is having issues connecting to the inverter via MODBUS it seems:
Modbus connection failed, connection could not be made or register range failed to be read.
Does MODBUS work over WiFi? Or ethernet connection is required?
Iāve also seen some forums which suggest Sungrow started encrypting the MODBUS traffic, not sure if this was the cause.
Edit:
Yep that definitely looks to be the case, there are different WiFi modules and some are encrypted. Someone on Whirlpool has written a script to read from the Websocket via its local access web portal instead, I may look to integrate this when I get some time. https://forums.whirlpool.net.au/thread/3vxm5jy3?p=11#r214
This should be compatible with the SungrowInverter client that you wrote @mvandersteen
Iām having an issue with assigning a static IP to my Sungrow inverter so I can consistently read the data into HA.
Iāve assigned it an IP via my routerās DHCP settings and Iāll usually get a couple of days where the inverter turns off overnight and comes back up correctly. However, every so often it will come back up with a different MAC address (ie. 02:A0:00:36:30:4E vs 02:A0:00:C0:0F:E6) and the router will give it a new IP address, thinking itās a different device.
Is this just something that should be expected? How can I reliably get the readings if both MAC and IP addresses keep changing?
@mvandersteen Iād like to get data from my SG5K-D into HA
i see you have added support for the Hybrid units, will you be adding support for the string models?
on a separate question to see if the Modbus encrypting traffic will be an issue for me, is the firmware updated automatically on these units or a manual process, and how do you tell what version of firmware it is running?
Iāve just today finally got some data from my SG5K-D correctly into HA via modbus - after months of pulling my hair out. Turns out I needed to offset all the addresses that are reported in modbus mappings by -2 (even though solariot gives me the standard modbus register numbers). Donāt know why. But now it works. Hereās configuration (in configuration.yaml) for PV generation and grid voltage:
I have just had a PV system installed today with the same inverter.
Are you using that standard Wifi module that came with the system.
If so was there anything you needed to do to get communications working with it on Modbus other than putting your config in to HA?
I believe itās the standard wifi module. It was all pre-installed on the house we purchased. Other than setting it up to connect to our network there was nothing else I had to do. I donāt know if maybe some have newer firmware that encrypts traffic but I didnāt have that with mine.
I have a SG10KTL-M inverter. It was there when i bought the house, no documentation.
It has a very old communication module (CDMA 1X, no documentation can be found) connect to the RJ-45 communication port.
I replace the communication module. new module is a 485 to Wi-Fi module. The communication port RJ-45 pin 1 is +5V, pin 2 is GND, pin 3 is 485 B-, pin 6 is 485 A+.