Custom Component: SolarEdge Modbus TCP

If you have a SolarEdge inverter that support Modbus TCP, just install this custom component and start getting lots of real-time (every 5sec) data into your home assistant!

1 Like

Hi, Thanks for this and I am interested in it.
In your opinion, what would be the difference between this and using the native HA MODBUS component?

@wmaker hi, of course this needs to be clarified what the benefits for using this is.

I started using the native modbus integration, but for every register you add, home assistant will make one request/reading and extract only that register value.

This means that if you want to extract many values along with their scale factors it can potentially (and this happened for me several times per day) get a current value and it’s scale factor mismatched due to the inverter changed it just between two readings.

This caused some readings to momentarily become a factor 10 or more wrong, for example power output could show 20000 watts instead or 20 or similar.

This custom component reads all registers atomically in the same reading every 5 second which makes it both reduce the amount of readings/requests made and also always get the correct values!

It also provides an easy “drop in” / copy paste configuration to avoid having to figure out all the registers numbers on your own

Cheers

3 Likes

Amazing. I just had my SolarEdge inverter activated a few days ago, and was so disappointed that the local LAN API was removed on the most recent firmware update (released after I signed the contract for the system, grumble). So I research and find that the information is still available over Modbus, and then one day later you release this component. How awesome is that!

Anyway. I’m running Hass.io and had to make one change (so far) to your component. As presently written, solaredge_modbus requires pyModbusTCP, which I could not figure out how to expose to the Docker instance from the host’s Python install. So I ended up uploading pyModbusTCP under your component folder, and added a line to your __init__.py (third line below):

import logging

import voluptuous as vol

from . import pyModbusTCP
from pyModbusTCP.client import ModbusClient

...

And that seemed to satisfy it. Would you say this is the suggested way to handle this, or is there a better way? I’m just getting started with HomeAssistant scripting.

Thanks for your work on this component, and for keeping me from pulling my hair out trying to find a workaround for the missing API :slight_smile:

EDIT This isn’t necessary now, see below.

A couple of other things. For US split-phase 240V inverters, output voltage is reported on register 40077, I_AC_VoltageAB. Also, I wanted to track the current inverter status, which is available on register 40108. So I made the following additional changes to your sensor.py:

                    #40076
                    ac_current_scalefactor = 10**data.decode_16bit_int()

                    values['ac_total_current'] = self.round(ac_total_current * ac_current_scalefactor)
                    values['ac_current_phase_a'] = self.round(ac_current_phase_a * ac_current_scalefactor)
                    values['ac_current_phase_b'] = self.round(ac_current_phase_b * ac_current_scalefactor)
                    values['ac_current_phase_c'] = self.round(ac_current_phase_c * ac_current_scalefactor)

                    #40077-40079, AC Voltage AB, BC and CA
                    ac_voltage_phase_ab = data.decode_16bit_uint()
                    ac_voltage_phase_bc = data.decode_16bit_uint()
                    ac_voltage_phase_ca = data.decode_16bit_uint()

                    #40080-40082, AC Voltage AN, BN and CN
                    ac_voltage_phase_a = data.decode_16bit_uint()
                    ac_voltage_phase_b = data.decode_16bit_uint()
                    ac_voltage_phase_c = data.decode_16bit_uint()

                    #40083
                    ac_voltage_phase_scalefactor = 10**data.decode_16bit_int()
                    
                    values['ac_voltage_phase_ab'] = self.round(ac_voltage_phase_ab * ac_voltage_phase_scalefactor)
                    values['ac_voltage_phase_bc'] = self.round(ac_voltage_phase_bc * ac_voltage_phase_scalefactor)
                    values['ac_voltage_phase_ca'] = self.round(ac_voltage_phase_ca * ac_voltage_phase_scalefactor)
                    
                    values['ac_voltage_phase_a'] = self.round(ac_voltage_phase_a * ac_voltage_phase_scalefactor)
                    values['ac_voltage_phase_b'] = self.round(ac_voltage_phase_b * ac_voltage_phase_scalefactor)
                    values['ac_voltage_phase_c'] = self.round(ac_voltage_phase_c * ac_voltage_phase_scalefactor)

...

                    temp_sink_scalefactor = 10 ** data.decode_16bit_int()
                    values['heat_sink_temperature'] = self.round(temp_sink * temp_sink_scalefactor)
                    
                    #40108: Status
                    values['status'] = data.decode_16bit_uint()

                    #calculate efficiency
                    if values['dc_power_input'] > 0:
                        values['computed_inverter_efficiency'] = self.round( values['ac_power_output'] / values['dc_power_input'] * 100 )
                    else:
                        values['computed_inverter_efficiency'] = 0

and added these to my configuration.yaml:

sensor:
  - platform: template
    sensors:
      solaredge_ac_total_current:
        friendly_name: "SolarEdge AC Output Current"
        value_template: "{{ state_attr('sensor.solaredge_modbus', 'ac_total_current') }}"
        unit_of_measurement: 'A'
      solaredge_ac_voltage_phase_ab:
        friendly_name: "SolarEdge AC Output Voltage"
        value_template: "{{ state_attr('sensor.solaredge_modbus', 'ac_voltage_phase_ab') }}"
        unit_of_measurement: 'V'

...

      status:
        friendly_name: "SolarEdge Status"
        value_template: >-
          {% if state_attr('sensor.solaredge_modbus', 'status') == 1 %}
            Off
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 2 %}
            Sleep
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 3 %}
            Wake-Up
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 4 %}
            Working
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 5 %}
            Throttled
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 6 %}
            Shut-Down
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 7 %}
            Fault
          {% elif state_attr('sensor.solaredge_modbus', 'status') == 8 %}
            Maintenance
          {% else %}
            Unknown
          {% endif %}
1 Like

@datagon Great that you found it useful and thanks for the contribution. I will add it to the project at github! However weird that you had to modify that pyModbusTCP python import, I’m actually also running hass.io! Maybe I have some local change that makes it work anyway. I’ll look into it

I wonder if the host you start with makes a difference. I’m running on Debian 10 using the generic Linux install procedure from Home Assistant. Maybe something was missing at install time?

Regarding the pymodbusTCP it is listed as an requirement in the manifest, however I see that Ive got a casing incorrect as it should be pyModbusTCP, I updated it… Home assistant should try and download the dependencies while starting up if they are missing, so it should not be recommended to upload these files manually what I know… Try if it works better now!

It still seems to work after I update the casing and remove my initial mods and the local pyModbusTCP library, so that must have been it. Thanks!

1 Like

I added all your proposed changes to the github repository, also added the B-C and C-A voltage template sensors and friendly names to all other sensors in the example config.

A tip if you have not already done it, is to add influxdb and grafana to your hassio instance, then your values automatically gets copied into there and you can pull some really cool statistics and graphs with alot higher performance

Im glad I found this. My inverter is coming online later this week, and glad i dont have to rely on the cloud to get the data out!

1 Like

Unfortenately you need the cloud to see specific optimizer/panel data with their own app as that is not a part of the sunspec standard. Not even available through their api… for all other usage, this gives you most data you need!

My internet can be flakey at times, so its an extra nice to have on the occasions that it goes down!

Hi, I’m really interested to use this component. However I’m not sure I can. My meter is the SolarEdge Modbus but it is not connected directly to my Lan so not sure about the TCP part, it is connected only to my solaredge inverter via 485 not TCP, can I still get its data from my inverter IP using port 1502?? as your configuration suggest?? Thanks in advance!!

Hi @jolaca this component do only communicate with your inverter. You however need to enable “ModBus TCP” in your inverter for this to work. The external modbus hardware is not even needed for this component to work, I don’t have it myself.

Thanks @erikarenhill, I have already setup your component and it has generated lots of sensors, however their values are not active yet. As you said, it should be that I don’t have enabled the ‘Modbus TCP’ option in my inverter. The user they set up for me doesn’t have access to the SetApp solaredge app so I have asked my installer via email to grant me access in order to change that option. I do have access to their monitoring web as admin, but from what I see, there’s no way to access that option from the web. Is there any easy method to be able to activate the ‘Modubus TCP’ option?? Thanks again!!

@jolaca it depends on your inverter model and firmware. If you can use the mySolarEdge app to connect locally to your inverter it might be possible to change this on your own. You can also try and contact solaredge support directly if they can activate it. Just ask for modbus tcp activation

1 Like

Hi again @erikarenhill, thank you very much!! finally I’ve managed to access SetApp app and I have already changed to ‘enable’ the modbusTCP option. Now I can see the sensor with their values. However I have a doubt now: using your sample file to generate the sensors, I do not see the most important sensors for me: grid_power, current_power and consumption. Are they available from the modbus?? Is there a list with all the sensors or something? Thank you!!

@jolaca Glad you got it working.

Current power is ‘solaredge_ac_power_output’ this is the amount of power currently produced the last reading

Consumption I believe is data from your separate hardware modbus meter which is not implemented as I don’t have one myself to test with.

Not sure what grid power is, do you mean exported power? The amount of production minus the consumption?

If you add a sensor to the dashboard just type solaredge and scroll through the autocomplete list and you find all available sensors there.

Edit: looking at the spec it looks like it would be possible to read all values from the external modbus meter through this protocol as well but would require some work and I would not be able to test it. Feel free to add a pull request on GitHub if you know some programming and get it to work

1 Like

Thanks @erikarenhill. Having the modbus meter installed lets you know besides the power that your PV setup is giving 2 more parameters:
Consumption: it is the power your house is demanding in that moment.
And grid_power: it’s the power that you are getting from the grid to supply the power demanded by your house. If solar_power = 0 (in the night), grid power = consumption. However during the day:
if solar power< consumption --> grid+solar = consumption
if solar power> consumption and your installation can export --> grid = solar - consumption
if solar power> consumption and you cannot export --> solar adjusts to consumption and grid_power=0
Solaredge cloud api lets you access to these 3 sensors, but only every 10 minutes!
It would be great to be able to implement grid and consumption using the modbus meter data. We could then get locally what the SolarEdge app displays. Here’s an example from the web:


Could I help to try to implement it??