Integration of a Fronius Symo Gen 24 plus Inverter via Modbus TCP

Okay! Thanks farmio.
I will try it over TCP Modbus (Register numbers)

nice evening

Hey guys,

I’m very new to the whole HA scene and slowly getting my head around it’s implementation. At this stage i’m struggling to get this code to work, specifically the raw register values listed here:

       - name: reading_inverter_multiple_raw
        slave: 1
        count: 88
        address: 40265
        scan_interval: 2
        data_type: custom

I’ve checked the fronius documentation and it all looks ok for my very novice understanding of modbus over tcp, so not sure where i’m going wrong?

It would also be great to include the code for riemann sum and the defaults required for the energy selector so that it can be copy and paste for others that aren’t as familiar (like me!).

Any help would be appreciated!

Hi,
If I were in your place I’d start with smaller register arrays to get a general knowledge if that retrieves any data at all.
The register/count/data you can read depends heavily on the device you use, firmware version, and also on the settings of the device (like float/int+sf setting makes a huge difference both in data reading methods and register addresses.
Try posted configs, start small, scale up on success :wink:

Hi @demon1300, do you have specific errors that you are getting? If there is nothing in the logs, try reducing the complexity and query some values manually (e.g. starting at 40265 and see if you can get the correct scaling factor).

Hi :wave:!
I’m extending the HA built-in Fronius integration (via http SolarAPI, not Modbus).
I’m looking for some example data from various systems to further extend and test it. I myself own a Symo with an Smartmeter so I’d be very interested in data from different systems:

  • Gen24 :white_check_mark:
  • Hybrid
  • multi-inverter systems
  • Ohmpilot :white_check_mark:
  • Wattpilot :white_check_mark: (apparently not supported by Fronius’ SolarAPI)
  • any batteries connected :ballot_box_with_check:
  • anything I’m not even aware of :rofl:

If you happen to have access to such a system and are willing to help please ping me here or via discord (farmio#5918).
Thanks :+1:

PS: also beta-testing the currently implemented devices (Inverters, Batteries, Meters, Loggers) with the new integration coming with 2021.12 release would be much appreciated.

Hallo Matthias,

ich besitze selbst eine Anlage mit Gen24, BYD Batterie und Wattpilot und wäre sehr interessiert an einer besseren Integration in HA.
Gerne kann ich Daten zur Verfügung stellen.

sg Franz

1 Like

Same configuration, gen 24 + HVS Byd

I can also help

Thank you both for your offers :+1:! Meanwhile I have received data from 2 Gen24 systems (with and without battery and ohmpilot) and already added this as test data for the new Fronius HA integration.

Ohmpilots are not yet supported by the used library, but it is not a big deal to add it once merged to pyfronius

Fronius Wattpilot seems to not be part of the SolarAPI system - it doesn’t appear in any response. Maybe it will with a future software update. They don’t seem to take the integration of their own API very serious :roll_eyes:

I couldn’t have said it better…

Hi!

As I have 2 arrays facing different directions on my roof, i was always interested on the power readings for separate DC strings.
Comparing reality with their API docs was the hardest part :slight_smile:
Please check my configuration above (17)
Thanks

The http API on Symo devices returns 2 sets of current and voltage but they don’t seem to represent its 2 MPPTrackers at least on my system - i only get data for one set.
(IDC, UDC, IDC_2, UDC_2)
On Gen24 devices there are even 3 sets (maybe 1 for battery?) and I have seen data on 2 of them :man_shrugging:

I personally have zero experience with Modbus so I can’t help you there.

Hi - looks like the discussions are more on the HTTP API side. Would you mind to shift this over to a new forum topic/thread to keep it separate from the Modbus TCP integration topics?

On Modbus (TCP) Fronius offers to read data for the two DC strings separately. As far as I can see the delivered data is in line with what you would expect. If you need more input/help with this, let me know.

KRs

1 Like

You are absolutely right, I didn’t intend to hijack this thread.

Would you know if the Modbus registers on different Fronius devices (Symo, Hybrid, Gen24, IG, …) are equal for the same datapoints or are there individual register tables for every system?
And further how frequent do the values change?
Is there a limit how frequently they can get queried (there is on HTTP)?

Would you know if the Modbus registers on different Fronius devices (Symo, Hybrid, Gen24, IG, …) are equal for the same datapoints or are there individual register tables for every system?

As far as I have seen, there are slight differences between the products in the register numbers. For the new Gen24, Fronius released a new set of documents which describe the Modbus registers.

There is a disclaimer in the documentation about the register numbers (in German)

And further how frequent do the values change?
Not sure if this question is related to the values of the registers or the register numbers themselves.

  • Up to now, the register numbers did not change (I’ve upgraded the inverter FW whenever possible). Feedback from other users was that many of them could use my examples without the need to change register addresses.
  • The values in the registers are updated in near real time (I have been able to monitor/analyse how the inverter deals with sudden power demand increase by collecting consumption from grid / power drawn from the battery by collecting the values in very high frequency)

Is there a limit how frequently they can get queried (there is on HTTP)?

I do not have reliable information on the Modbus side, but I expect that the “stack” stress on the inverter is much less compared to queries via HTTP. In my setup, I’m continuously polling every 2 seconds - shorter polling cycles cause issues on my HomeAssistant instance to process the data. I can still use a second modbus client to execute parallel requests and the inverter does not seem to care a lot about this - so the load seems to be rather low.

Um … just found something in the documentation (in German)

1 Like

Dear Oscar,

really appreciate your work here. It was essential for me to retrieve data from my SymoGen24, battery and main meter. I’m a sort of beginner in HA even if I have some programming background in other languages (always self teaching) … so I’m a bit confused in your configuration for what is below:

       data_type: custom
        # Registers and positions in custom structure
        # 0  DCA_SF
        # 1  DCV_SF
        # 2. DCW_SF DC Energy scaling factor
        # 3. DCWH_SF
        # 4  1_ID
        # 5  1_DCA
        # 6. 1_DCV
        # 7. 1_DCW Energy string 1
        # 8  2_ID
        # 9. 2_DCA
        # 10 2_DCV
        # 11 2_DCW Energy string 2
        # 12 3_ID
        # 13 3_DCA
        # 14 3_DCV
        # 15 3_DCW Energy to battery, charging
        # 16 4_ID
        # 17 4_DCA
        # 18 4_DCV
        # 19 4_DCW Energy from battery, discharging
        structure: ">hhhh8x H16xHHH16x H16xHHH16x H16xHHH16x H16xHHH16x"

I’ve googled to look for custom data type and structure but I didn’t find any specific explanation.
Could you please point me to a tutorial or manual to understand how it works ?

In your example you collect 88 register and then with this declaration you can list them from 0 to 19 as a parameter even well split by data type !!! amazing …

I want to extract “Life time energy” but I did it by addressing it directly not using multiple register read as you did…

Many thanks
Francesco

Hi Francesco,
glad to hear that this was useful for someone out there :slight_smile:

I’ve googled to look for custom data type and structure but I didn’t find any specific explanation.
Could you please point me to a tutorial or manual to understand how it works ?

I believe this question is specifically about how to unpack the data that has been received from the inverter. I was using the Python documentation about binary structures - see here: struct — Interpret bytes as packed binary data — Python 3.12.2 documentation - plus some heavy trial and error.

At the end of the document there is a reference table of Format Characters - you will recognize those in my code. There are also some examples included how to do shortcuts: e.g. 8x means “8 padding bytes in a row”

I hope this was helpful, let me know if you have further questions.
Kind regards,
Oscar

Hi Oscar,

many thanks for taking time to reply. I’m still need to study your script and also the Python doc… (I’m newbie). I’ve succeed to include Energy by reading directly the register (40285) then tempating by multiplying it for its multiplier…

Then to learn from your code:

  • you read 88 (registers, 16bit) from modbus TCP
  • data type: custom is required to keep the read values as they are…
  • structure: “>hhhh8x H16xHHH16x H16xHHH16x H16xHHH16x H16xHHH16x” directive let you to unpack each according to its type (short, unsigned short,…) as described for each in Fronius modbus table.
    It’s correct to say ? “>” big endian, the first 4x “h” means firs parameters are unsigned short,…
    so then in each index you will have the parameters decodified and ready accordingly…
    am I correct ?
    Still I can’t understand “8x” or “16x”. They might represent a parameter made of bit … but it doesn’t seem to match with Fronius table or even the list you provided becasue only ID might be this type of data… what I miss ?

Regards
Francesco

Thank you for this !!
I was able to get the string power finally on my setup with Symo 10.
Can you please share how to get the voltages also please? DC voltage for strings and AC voltage for phases :slight_smile:

Or even better the codes/sensors for all the data from Modbus :slight_smile: - or at least everything you have.
I know it is a lot, and i’ve tried for at least 8 hours to do it myself, but it is well over my head …
Now i am using the API requests but i’d like to switch everything to modbus as it seems much better and faster.

Thank you

Hi Oscar @soly3141

Did you get any further with your plans to control the power flow to/from the battery? I’m in the phase to choose inverter and that is a hard requirement for me that I can control dynamically when to charge and discharge the battery (and preferable from Home Assistant).

/Henrik

Hi,

I’m glad it helped. It is really not that hard once you figure it out for the first time - but the first time indeed - not that easy.
I followed a document called Modbus_TCP_RTU.pdf, downloaded from Fronius after registration.
Check the data you need:
i.e. AC power.
Search and find, keep in mind in my example I use int+SF (whole numbers + scale factor. If you have 50 as data and -2 as SF, data must be multiplied by 10 on the power of SF - in our example 50* 10^-2 = 50 * 0.01 = 0.5W)

After some trying and using modbus testing tool, you realize the doc is off by 1 register address as counting starts from 0 → so you’re looking for 40083 as start
you need 2 registers → count: 2
and you need an unsigned integer as data (watts never go below 0 ), and a signed as scale factor → structure: “Hh”
(source: struct — Interpret bytes as packed binary data — Python 3.10.4 documentation )

Then do the math in the template sensor by using the above dataset and split that az every colon char.

The MPPT values are trickier as those are not often together:
image


Remember, registers are off by 1, so startaddress + line address - 1
We start with register 40257
We need 38 registers in total
data is like Signed integer(h) + 32 junk(32x) + unsigned integer(H) + 38 junk(38x) + unsigned integer(H)
Junk registers will be skipped simply.
I’m not sure how this works with a smart meter, but from the docs it seems if you have monitoring tied to the inverter, you even could get consumption data out the same way.

You may also use float, for me hat did not work out somehow. Int+SF is rock solid if you read both values in the same entity. If it is divided to different modbus entities, there will be spikes as they won’t always align.

Hi Henrik @hossians,
I did, it’s working for me but might need some polishing before ready to release. At the moment, I’m managing when and how quickly the battery will be charged. Due to regulations here, my AC output to the grid is limited by 70% of the total kWp installed. Im fetching forecast data for PV production from solcast.com. If the forecast is above a certain threshold I limit battery charging to the peak hours of the day to make sure the system is always 100% productive.

The main part is to control the charging flow, this is done with the following command:

service: modbus.write_register
data:
  unit: 1
  value: '500' # charging value in Watt 
  hub: fronius1 # name of your modus hub
  address: 40366 # rmodbus register to control charging "InWRte" (-1 offset observed in the register numbering) 

If you want to control discharge, you can use address 40365 “OutWRte”

In my automation, it looks like this

# Solar Battery Charging Configuration
- alias: WRBatteryStoreExcessEnergy7k
  trigger:
    platform: numeric_state
    entity_id: sensor.derived_energy_pv_output_total
    above: 7000
    for:
      minutes: 2
  condition:  "{{ states('sensor.solcast_forecast')|int > 40 }}" 
  action:
    service: modbus.write_register
    data:
       unit: 1
       hub: fronius1
       address: 40366
       value: '1200'

The improvement I would still do is to implement some state information that charging has already been configured if this has triggered once - otherwise, in case of clouds or other impacts to your solar production, the condition is met multiple times in a short period and the register is written more often than necessary.

1 Like