Hi all,
I’ve spent the last couple of days to integrate my inverter into Home Assistant and wanted to share with everyone who likes to go down the same route.
My integration relies on the ModbusTCP protocol which is supported by Home Assistant. I had a look at the Fronius integration which is also available but decided to go the Modbus way, mainly because:
a) I’m planning to dynamically manage battery charging settings (not available in the Fronius integration)
b) I’m pulling values from the inverter every 1-2 seconds, something for which Modbus was designed to work and I’m not sure if the http/JSON API which is used by the Fronius integration keeps up with such load over a longer time
Some comments / pre-requesites for the implementation:
- if you are looking for the Fronius Modbus documentation, make sure to have the most recent one for the Gen 24. I struggled a lot because I was using old register information.
- You need to enable Modbus TCP on the inverter (connectivity settings)
- You need to configure the main meter address in the modbus TCP setting (mine is set to 200) - you need to use this in the modbus sensor configuration
- Consumption is calculated as: Inverter AC Power Out - Power Delivered To Grid
- If you have some ideas how to improve the template sensors or make the implementation more efficient I’m more than happy to listen to your suggestions
Update July 2021: the modbus configuration style has changed and since version 2021.7 the old style won’t work anymore. I have updated the post with the current working style. I have also changed the way how to collect certain registers in one pass to avoid situations in which values change to quickly and you will get wrong scaling factors.
Update April 2022: due to changes of data type handling in the modbus integration starting from release 2022.4, the configuration needs to be adapted. (see 2022.4: Groups! Groups! Groups! - Home Assistant and Remove generic data types INT, UINT, FLOAT in modbus by janiversen · Pull Request #67268 · home-assistant/core · GitHub).
Modbus Configuration and Registers
modbus:
- type: tcp
host: 192.168.x.x
port: 502
name: fronius1
sensors:
- name: reading_energy_main_meter
slave: 200
scan_interval: 2
count: 2
address: 40097
data_type: float32
unit_of_measurement: W
- name: reading_energy_inverter_ac_output
unit_of_measurement: W
slave: 1
count: 2
data_type: float32
address: 40091
scan_interval: 2
- name: reading_energy_battery_soc_scaled
slave: 1
count: 1
data_type: uint16
address: 40361
scan_interval: 2
- name: reading_inverter_multiple_raw
slave: 1
count: 88
address: 40265
scan_interval: 2
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"
Derived Template Sensors
derived_energy_consumption_total:
friendly_name: "Currently consumed electrical energy"
value_template: "{{ (states('sensor.reading_energy_inverter_ac_output') | int + states('sensor.derived_energy_from_grid') | int - states('sensor.derived_energy_to_grid') | int) | int }}"
unit_of_measurement: 'W'
derived_energy_battery_soc:
friendly_name: "Batterie SoC"
value_template: "{{ ((states('sensor.reading_energy_battery_soc_scaled') | int) * (10 ** -2 )) | round(0)}}"
unit_of_measurement: '%'
derived_energy_pv_output_string2:
friendly_name: "PV DC Output String 2"
value_template: "{{ (((states('sensor.reading_inverter_multiple_raw').split(',')[11] | int)) * (10 ** ((states('sensor.reading_inverter_multiple_raw').split(',')[2] | int)) )) |round(0)}}"
unit_of_measurement: 'W'
derived_energy_pv_output_string1:
friendly_name: "PV DC Output String 1"
value_template: "{{ (((states('sensor.reading_inverter_multiple_raw').split(',')[7] | int)) * (10 ** ((states('sensor.reading_inverter_multiple_raw').split(',')[2] | int)) )) |round(0)}}"
unit_of_measurement: 'W'
derived_energy_pv_output_total:
friendly_name: "PV DC Output String Total"
value_template: "{{ ((states('sensor.derived_energy_pv_output_string1') | int + states('sensor.derived_energy_pv_output_string2') | int)) }}"
unit_of_measurement: 'W'
derived_energy_tobattery:
friendly_name: "Energy To Battery"
value_template: "{{ (((states('sensor.reading_inverter_multiple_raw').split(',')[15] | int)) * (10 ** ((states('sensor.reading_inverter_multiple_raw').split(',')[2] | int)) )) |round(0)}}"
unit_of_measurement: 'W'
derived_energy_frombattery:
friendly_name: "Energy From Battery"
value_template: "{{ (((states('sensor.reading_inverter_multiple_raw').split(',')[19] | int)) * (10 ** ((states('sensor.reading_inverter_multiple_raw').split(',')[2] | int)) )) |round(0)}}"
unit_of_measurement: 'W'
derived_energy_direct_consumption:
friendly_name: "PV Direct Consumption"
value_template: "{{ ((states('sensor.reading_energy_inverter_ac_output') | int - states('sensor.derived_energy_to_grid') | int)) }}"
unit_of_measurement: 'W'
derived_energy_to_grid:
friendly_name: "Energy to grid"
value_template: "{{ ((states('sensor.derived_energy_to_grid_inverted') | int) * -1 )}}"
unit_of_measurement: 'W'
derived_energy_combined_battery:
# to satisfy power wheel input requirements
friendly_name: "Energy to grid"
value_template: "{{-1 * (states('sensor.derived_energy_frombattery') | int - states('sensor.derived_energy_tobattery')| int )}}"
unit_of_measurement: 'W'
Filter Sensors
- platform: filter
name: "derived_energy_from_grid"
entity_id: sensor.reading_energy_main_meter
filters:
- filter: range
lower_bound: 0
precision: 0
- platform: filter
name: "derived_energy_to_grid_inverted"
entity_id: sensor.reading_energy_main_meter
filters:
- filter: range
upper_bound: 0
precision: 0
Sensor Overview
Inverter Modbus TCP Configuration