Solaredge Modbus Configuration for Single Inverter and Battery

UPDATE: @ryanm101 did some great cleanup work on my original package and has added a lot of nice automations to control battery charging. He has uploaded it to github for better management of the code. The repository can be found here: GitHub - ryanm101/hasolarcfg: Solar Package for Home assistant using Solaredge Modbus multi integration
I will fork his work to match my current configuration as well and will maintain future updates there.

UPDATE 2: I have created a fork here: GitHub - Remko76/hasolarcfg: Solar Package for Home assistant using Solaredge Modbus multi integration without battery automations
In this I have now my latest code, based on @ryanm101 organisation. I will delete the code from the second post, any further changes will be on Github.

I have posted my previous configuration for the SolarEdge Modbus in the past here:

I got a lot of positive feedback and a lot of nice responses so I decided to post my updated configuration here. Why did I change? Wellā€¦the Modbus Integration was not being maintained (it is now) and I got a warning that it might not work in the future, so I started looking for alternatives and with the tip from @s_ash found the ModbusMultiInverter integration from here:

This is a fork from the original integration but better maintained and also works for Multi inverter setups. So I modified my configuration to be based on this integration and cleaned up formulas using tips from @b80k and @Ashpork ā€¦Thanks for your inputs!!

NOTE: my configuration uses one inveter and one battery. With some small modficiations, this is simply adjustable to a multi inverter setup or a setup without battery. Some in the other thread already did this, so I suggest to look at that for information.

Soā€¦how does it look now? Well this is my Energy Dashboard:

with this configuration:

  - title: Solar
    path: solar
    icon: mdi:lightning-bolt-circle
    visible:
     badges: []
    cards:
      - type: energy-date-selection
      - type: energy-usage-graph
        title: Energy Usage
      - type: energy-solar-graph
        title: Solar Production
      - type: custom:tesla-style-solar-power-card
        name: Home Energy Flow
        change_house_bubble_color_with_flow: 1
        threshold_in_k: 1
        show_gap: true
        grid_to_house_entity: sensor.solar_grid_to_house_w
        grid_to_battery_entity: sensor.solar_grid_to_battery_w
        generation_to_grid_entity: sensor.solar_panel_to_grid_w
        generation_to_battery_entity: sensor.solar_panel_to_battery_w
        generation_to_house_entity: sensor.solar_panel_to_house_w
        battery_to_house_entity: sensor.solar_battery_to_house_w
        battery_to_grid_entity: sensor.solar_battery_to_grid_w
        battery_extra_entity: sensor.solaredge_b1_state_of_energy
      - type: custom:power-distribution-card
        title: ''
        entities:
          - name: Grid
            preset: grid
            icon: mdi:transmission-tower
            entity: sensor.solaredge_m1_ac_power
            unit_of_display: W
            decimals: 0
            invert_value: true
          - name: Solar
            preset: solar
            icon: mdi:solar-power
            entity: sensor.solar_panel_production_w
            unit_of_display: W
            decimals: 0
          - name: Home
            preset: home
            icon: mdi:home
            entity: sensor.solar_house_consumption_w
            unit_of_display: W
            decimals: 0
            invert_value: true
          - name: Battery
            preset: battery
            icon: mdi:battery-high
            entity: sensor.solaredge_b1_dc_power
            unit_of_display: W
            decimals: 0
            invert_value: true
        center:
          type: bars
          content:
            - preset: custom
              name: INV
              bar_color: var(--paper-item-icon-color)
              entity: sensor.solar_inverter_effectiveness_int
            - preset: custom
              name: BAT
              bar_color: var(--paper-item-icon-color)
              entity: sensor.solar_battery_effectiveness_int
        animation: flash
      - type: energy-distribution
        title: Energy Distribution
      - type: entities
        entities:
          - entity: sensor.solar_panel_production_daily
            name: Produced
            icon: mdi:solar-power
          - entity: sensor.solar_house_consumption_daily
            name: Consumed
            icon: mdi:home-lightning-bolt-outline
          - entity: sensor.solar_imported_power_daily
            name: Imported
            icon: mdi:transmission-tower-export
          - entity: sensor.solar_exported_power_daily
            name: Exported
            icon: mdi:transmission-tower-import
          - entity: sensor.solar_battery_in_daily
            name: Charged
            icon: mdi:battery-positive
          - entity: sensor.solar_battery_out_daily
            name: Discharged
            icon: mdi:battery-negative
          - entity: sensor.solar_lifetime_production
        show_header_toggle: false
      - type: entities
        entities:
          - entity: sensor.solar_accounting_cost_rate
            name: Importrate
          - entity: sensor.solar_accounting_compensation_rate
            name: Exportrate
          - type: custom:template-entity-row
            icon: mdi:plus
            name: Import Costs
            state: >-
              {{ ((states('sensor.solar_imported_power_daily') | float(0)) *
              (states('sensor.solar_accounting_cost_rate') | float(0))) |
              round(2) | replace('.', ',') }} ā‚¬
          - type: custom:template-entity-row
            icon: mdi:minus
            name: Export Compensation
            state: >-
              {{ -((states('sensor.solar_exported_power_daily') | float(0)) *
              (states('sensor.solar_accounting_compensation_rate') | float(0)))
              | round(2) | replace('.', ',') }} ā‚¬
          - entity: sensor.solar_accounting_total_daily
            icon: mdi:equal
            name: Electricity Bill
          - type: custom:template-entity-row
            icon: mdi:piggy-bank
            name: Cost Saving
            state: >-
              {{ -(((states('sensor.solar_panel_to_house_daily') | float(0)) +
              (states('sensor.solar_battery_out_daily') | float(0))) *
              (states('sensor.solar_accounting_cost_rate') | float(0))) |
              round(2) | replace('.', ',') }} ā‚¬
          - entity: sensor.solar_accounting_total_weekly
            icon: mdi:equal
            name: Electricity Bill Weekly
          - entity: sensor.solar_accounting_total_monthly
            icon: mdi:equal
            name: Electricity Bill Monthly
          - entity: sensor.solar_accounting_total_yearly
            icon: mdi:equal
            name: Electricity Bill Yearly
        show_header_toggle: false
      - type: custom:apexcharts-card
        series:
          - entity: sensor.solar_panel_to_house_daily
            name: Direct Consumption
            color: var(--energy-solar-color)
          - entity: sensor.solar_battery_out_daily
            name: Battery Usage
            color: var(--energy-battery-out-color)
          - entity: sensor.solar_imported_power_daily
            name: Imported Power
            color: var(--energy-grid-consumption-color)
        update_interval: 1min
        chart_type: donut
        apex_config:
          plotOptions:
            pie:
              expandOnClick: false
              donut:
                size: 50%
                labels:
                  show: true
                  value:
                    fontSize: 32px
                    fontWeight: 900
                  total:
                    show: true
                    showAlways: true
                    label: Autarkierate
                    formatter: |
                      EVAL:function(w) {
                        let values = w.globals.seriesTotals;
                        let total = values[0] + values[1] + values[2];
                        let self = values[0] + values[1];
                        return ((self / total) * 100).toFixed(0) + "%";
                      }
          dataLabels:
            formatter: |
              EVAL:function(value) {
                return value.toFixed(0) + "%";
              }
          chart:
            selection:
              enabled: false
          tooltip:
            enabled: false
          states:
            normal:
              filter:
                type: none
                value: 0
            hover:
              filter:
                type: none
                value: 0
            active:
              filter:
                type: none
                value: 0
          legend:
            onItemClick:
              toggleDataSeries: false
            onItemHover:
              highlightDataSeries: false
      - type: custom:apexcharts-card
        series:
          - entity: sensor.solar_panel_to_house_daily
            name: Direct Usage
            color: var(--energy-solar-color)
          - entity: sensor.solar_battery_in_daily
            name: Battery Charging
            color: var(--energy-battery-in-color)
          - entity: sensor.solar_exported_power_daily
            name: Exported Power
            color: var(--energy-grid-return-color)
        update_interval: 1min
        chart_type: donut
        apex_config:
          plotOptions:
            pie:
              expandOnClick: false
              donut:
                size: 50%
                labels:
                  show: true
                  value:
                    fontSize: 32px
                    fontWeight: 900
                  total:
                    show: true
                    showAlways: true
                    label: Self Consumption
                    formatter: |
                      EVAL:function(w) {
                        let values = w.globals.seriesTotals;
                        let total = values[0] + values[1] + values[2];
                        let self = values[0] + values[1];
                        return ((self / total) * 100).toFixed(0) + "%";
                      }
          dataLabels:
            formatter: |
              EVAL:function(value) {
                return value.toFixed(0) + "%";
              }
          chart:
            selection:
              enabled: false
          tooltip:
            enabled: false
          states:
            normal:
              filter:
                type: none
                value: 0
            hover:
              filter:
                type: none
                value: 0
            active:
              filter:
                type: none
                value: 0
          legend:
            onItemClick:
              toggleDataSeries: false
            onItemHover:
              highlightDataSeries: false
      - type: horizontal-stack
        cards:
          - type: custom:card-templater
            card:
              type: gauge
              entity: sensor.solaredge_b1_state_of_energy
              name: Batterieladung
              min: 0
              max: 100
              needle: true
              severity:
                red: 0
                yellow: 15
                green: 50
            entities:
              - entity: sensor.sensor.solaredge_b1_state_of_energy
                state_template: '{{ states(''sensor.solaredge_b1_state_of_energy'') | round(0) }}'
          - type: custom:card-templater
            card:
              type: gauge
              entity: sensor.solar_accounting_total_daily
              name: Stromrechnung
              needle: true
              min: -10
              max: 10
              severity:
                green: -10
                yellow: 0
                red: 3
            entities:
              - entity: sensor.solar_accounting_total_daily
                state_template: >-
                  {{ '%.2f' |
                  format(states('sensor.solar_accounting_total_daily') | float)
                  }}

Using a few custom elements:

Continued in next post

7 Likes

So my overall configuration to get all the sensors etc, follow these steps:

  • Install the integration mentioned above
  • Create a folder under /config called ā€œpackagesā€
  • In your configuration.yaml add the following:
homeassistant:
  packages: !include_dir_named packages
EDIT...code now on Github, see first post.

I will close the old thread, since i am not maintaining that configuration anymore. Any comments, questions or feedbackā€¦always welcome, I will do my best to answer it.

4 Likes

Sorry for such a silly question, but what card do you use to enter the code ?

That is the bit which gets created when you create a new page in Lovelace, maybe I better remove that bit.

1 Like

When you are editing a dashboard you can find the raw configuration in the overflow menu.
image

Itā€™s not a card, but the code for the whole dashboard which includes the cards.

1 Like

Thank a lot

Thanks for starting a new threadā€¦

Iā€™m just about to pull the trigger on a Solar install (SolarEdge obviously) and seems that ModBus over TCP is the way to go. At this stage, Iā€™m holding off on the battery, but other threads have talked about clamps etc.

Just to confirm, I can connect in via RJ45 to inverter and Iā€™m all good? There will be two inverters, if theyā€™re set up properly as a leader and a follower, do I just need the leader connected to the network?

Thanks.

Not the biggest expert on installation butā€¦
Yes, I would make sure your main inverter has the wired ethernet connection to your network and guess that is enough. I am assuming that the second inverter will share itā€™s data with the master through RJ45 (modbus) and your master is the one you query over modbus.
When it comes to clamps etcā€¦ In my installation I have a SolarEdge meter installed in my breaker box, directly after the 3 phases enter the house. It has 3 clamps for the 3 phases and is also connected through RJ45 (modbus) with my inverter. This meter is required to get data about self consumption, import and export.

1 Like

I dunno man. I have ethernet running to my router directly and modbus over TCP is working but I donā€™t get any data over M1, M2, or M3 channels for a reason that no one can take a guess at why or what is missing, so be careful and donā€™t expect this is a guarantee.

Thanks very much - looks like Iā€™ll need to get one of these added to my install thenā€¦

@Remko: Just saw that the old thread was closed. I read the initial post in this new thread. But I am not sure, if I understood all your points correctly. Maybe you can quickly clarify the following questions:

  • Is there any difference between old and new setup apart from ā€œWillCodeForCatsā€ instead of ā€œbinsentsuā€ and some non-functional formula refactoring?
  • Why are you saying ā€œbinsentsuā€ was/is not maintained (anymore)? Is there any problem with this integration that I missed?
  • I am currently running your old setup with Ashporks ā€œfixā€ and some own extensions on top. Do you see any benefit in moving to your new setup for my single-inverter-with-single-battery-setup?

Thanks for your answers. In any case I am happy that you are still driving and improving this topic.

@stephanschuster

  • no, there are no further differences. This integration offers support for multiple inverters (which I do not need) and I like the naming and structuring of the entities better. So overallā€¦in my setup, just cosmetic changes. I did the formula refactoring based on some of the recommendations in the other thread and learned some new things about yaml, that is why I updatedā€¦
  • Wellā€¦binsentsu did not bring out any updates anymore. A couple of releases ago, there was a significant change in Homeassistant which would have caused it to stop working. I forked the integration and made the necessary change, which he then incorporated. WillCodeForCats is actively developing his integration, plus the cosmetic differences made me change
  • So overallā€¦I do not see a benefit in your setup. Our setups are the same and besides the cosmeticsā€¦no benefit at all.

And yesā€¦I keep fiddling with HomeAssistant and since I like this setup, I always keep looking at improvements.

2 Likes

A few of us have issues getting any of the M1/M2/M3 sensor data. We get all the ā€œmainā€ data, but need the M1 data to make use of these dashboards. I have installed/uninstalled several times but no joy. Any ideas?

I donā€™t understand why they wouldnā€™t show. It is an issue of the integration though, have you opened an issue there?

Maybe a stupid question, butā€¦ What kind off setup do you have, I mean, do you actually habe an import/export meter installed? My parents have a setup without such a meter (which only issue required off you have a battery if I understand it correctly) and therefore do not get these entities of course.

  • no, there are no further differences. This integration offers support for multiple inverters (which I do not need) and I like the naming and structuring of the entities better. So overallā€¦in my setup, just cosmetic changes. I did the formula refactoring based on some of the recommendations in the other thread and learned some new things about yaml, that is why I updatedā€¦
  • Wellā€¦binsentsu did not bring out any updates anymore. A couple of releases ago, there was a significant change in Homeassistant which would have caused it to stop working. I forked the integration and made the necessary change, which he then incorporated. WillCodeForCats is actively developing his integration, plus the cosmetic differences made me change
  • So overallā€¦I do not see a benefit in your setup. Our setups are the same and besides the cosmeticsā€¦no benefit at all.

Thanks so much for clarification. Maybe you can give an explicit hint to all users of the old setup if youā€™re adding/fixing stuff which makes switching to the new setup worth it.

1 Like

See the instructions for filing a bug report issue on how to enable debug logging which will show low level info when the integration asks the inverter if it has any meters configured. Specifically, there are debug log lines that say ā€œInverter X meter Yā€ and some hex numbers like this:

A valid meter (as configured in the inverter through the front panel or SetApp) should respond with C_SunSpec_DID 0x1 and C_SunSpec_Length 0x41. If it doesnā€™t (in the example there is no meter 3 so Inverter 1 Meter 3 is 0x0 instead) or responds with other values then itā€™s not a valid meter according to the specs and you would need to open a support request with your installer or SolarEdge support asking why the meter doesnā€™t identify itself as a meter according to the published specs.

I am the author of solaredge-modbus-multi so hereā€™s my backstory about why my integration exists.

I started out looking for a way to get local data from my setup of two inverters and one meter. I searched a lot and it turns out very few (basically nobody) cared about setups that had more than one device, until I found someone had made a fork of an integration that did support two inverters. So I ended up using that fork of what Iā€™ll call it the ā€œotherā€ integration. At the time my knowledge of development for HA and Python was nonexistent, although I have plenty of experience with C/C++, Perl, PHP, and other languages. Just never Python.

I started using the other integration and tested the PR, but it quickly became apparent that the author had no intention of actually merging the PR for multiple inverter support, but did merge requests for other stuff. I donā€™t know why, but it was critical to me so I started a fork that included the PR I needed and tried to backport upstream changes into my fork, but that also eventually ran into my Python knowledge limits at the time.

In the meantime I decided to try to learn how to write a complete integration from scratch for a Tekmar home automation gateway integration since literally none existed: my tekmar-482 integration and tekmar-packetserv add-on. I learned a hell of a lot about HA development and Python after tackling that task, then I took all of that knowledge and applied it to a ground-up rewrite for my solaredge-modbus-multi integration. Iā€™ve tried to adhere to HA developer guidelines and practices, keep up on HA changes, and make sure the integration works as well as I want it to work since Iā€™m actually using it for myself. That means I want my work to be robust and error free as possible.

The only thing my integration lacks over the other one is that solaredge-modbus-multi doesnā€™t have power control command support. This is because I donā€™t personally have any batteries, but I am slowly working through that using a modbus simulator to pretend to be a battery using data based on other userā€™s debug logs (since I donā€™t have a real battery to develop with). So it will eventually have that feature too, but obviously without real hardware on my end and most people still wanting to stick with the other integration means less demand for that feature and fewer testers for me. The beginning of that work is in PR #117 and the power-control branch. (It has control options added since this was written.)

Iā€™m biased but I think my integration is better maintained, more robust, and higher quality. I just took a glance at all the open issues and complaints in the other integrationā€™s ā€œissuesā€, and my impression is that I think that my solaredge-modbus-multi integration fixes or addresses almost every compliant, problem, or defect present in the other one. I take pride in trying to quickly address issues that are brought up, especially if itā€™s a bug I missed, because I do not want to ship low quality or incomplete releases. Since I do use my own integration I see things over time that can be done better.

Thatā€™s the basic story behind why solaredge-modbus-multi exists. Even if nobody used it I would still be working on it because I use it for my system, but Iā€™ve added a lot of features for stuff I donā€™t have since other people do use it instead other options. For example, I recently added SolarEdge Synergy support which is something I was aware of but didnā€™t originally spend time on since Synergy inverters are large three phase commercial systems up to 120kW, not something I thought HA would be connected to, but someone did so I added support for it.

Of course, if you are happy with the state of the other integration then by all means keep using it.

Edit: The v2.2.7 release of solaredge-modbus-multi will add support for battery commands.

7 Likes

@WillCodeForCats, thanks for this detailed explanation. I am a software developer myself, so I fully understand your points and can totally value your work and motivation. Much appreciated. In the near future I will definitely switch to your integration. The only thing which hindered my so far was the fact that the old one is working stable and a switch would cost me quite a bit of time since I extended @Remko old setup quite a bit for my own purpose. Anyways, by the end of the year I will have switched. Keep up your work. Thanks.

Quick question: I did not understand ā€œpower control command supportā€. What is this for? When would I need it? I have a battery. But as far as I understood, this is supported by your integration even tough you donā€™t have a battery yourselves.

@Remko and @WillCodeForCats thanks for the info. I am not sure how to enable the detailed logging you are showing but that looks like my next step, then I can file a bug if the DID shows 0. Are there instructions for enabling detailed debugging?

If the DID and Length are not 0x1 and 0x41 respectively, then itā€™s not a bug, the inverter is saying it doesnā€™t have a meter configured. Those are a header that say ā€œyes there is a meter in this config slotā€ if set to those values.

If you click on the bug report template under issues that template has instructions for logging configuration for your configuration.yaml file.

Edit: I should say itā€™s not my bug to fix. If you actually have a physical meter (assuming it was commissioned properly) and the inverter is still saying no meter then thatā€™s a question for SolarEdge support or your installer.