Fronius Solar, BESS, EV Charging

This is the back-end services for my Home Energy Management dashboard.

I have been cleaning up automations that have sprawled over the last 5-years. One of these clean-up was replacing my old and, simple solar inverter with a shiny new one.

The new solar system is a substantial improvement on the old one. As soon as it was added, I realised some gaps.

What are the questions this is trying to answer

  • How can I control my renewable assets without another vendor app or two?
  • How to save money? (Set and Forget)
  • What did my stuff do? (Notes and detailed logs)
  • What is my stuff doing now (Control)

Here is the critical hardware used:

  • Fronius GEN24 (Inverter)
  • Fronius Smart IP Meter
  • Fronius Reserva Battery Energy Storage Solution (BESS)
  • Fronius Wattpilot Flex (EV Charger)

Associated articles:

Here is what you will need to complete this setup:

  • Home assistant + HACS
  • Static IP address for inverter (or smart meter) and EV charger
  • Inverter will require the technician password or at least the technician to enable some settings for this to work (username + password)
  • EV charger will require the serial number and the default password

Step 1:
Add custom repo’s in HACS (http://homeassistant.local:8123/hacs/dashboard → 3 dots menu in top right → custom repositories)

https://github.com/callifo/fronius_modbus
https://github.com/mk-maddin/wattpilot-HA

Step 2.
Restart Home Assistant

Step 3.
Add integrations (http://homeassistant.local:8123/config/integrations/dashboard > +Add integration)

Fronius Modbus
Fronius Wattpilot

Step 4.
See what automations for your use case. For my personal use case, I am in Perth, Western Australia, using the Synergy time-of-use tariff. I have the following goals for my renewables investment:

  • Peak Shaving: Discharging stored battery power during expensive peak-demand hours to reduce commercial utility “demand charges”.
  • Energy Arbitrage: Charging the batteries when electricity is cheap (e.g., in the middle of the night) and discharging them when grid prices are high.
  • Renewable Integration: Storing excess energy generated by onsite solar panels for use when the sun isn’t shining.
  • Grid Services (VPP or Virtual Power Plant): Participating in demand response programs to stabilise the local utility grid and even generate revenue.
  • Grid Resilience (Blackout protection): Participating in demand response programs to stabilise the local utility grid and even generate revenue.

Here is some more information on this VERY loaded topic Rapid backup understanding UPS vs BESS technologies

Step 5.
Deploy appropriate automations

Energy Tariffs changer

alias: Energy Tariffs changer
description: >-
  This routine is for a 4-tier Time of Use (TOU) tariff from Synergy in Western
  Australia.


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454
triggers:
  - at: input_datetime.tou_06_00_off_peak
    variables:
      tariff: Off Peak
    trigger: time
  - at: input_datetime.tou_09_00_super_off_peak
    variables:
      tariff: Super Off Peak
    trigger: time
  - at: input_datetime.tou_15_00_peak
    variables:
      tariff: Peak
    trigger: time
  - at: input_datetime.tou_21_00_off_peak
    variables:
      tariff: Off Peak
    trigger: time
  - at: input_datetime.tou_23_00_overnight
    variables:
      tariff: Overnight
    trigger: time
actions:
  - parallel:
      - target:
          entity_id: select.tou_em_channel_b_energy
        data:
          option: '{{ tariff }}'
        action: select.select_option
      - action: logbook.log
        metadata: {}
        data:
          entity_id: select.tou_em_channel_b_energy
          domain: automation
          message: '#Automation told me to do it.'
          name: sensor.main_line_em_channel_b_energy
      - choose:
          - conditions:
              - condition: state
                entity_id: select.tou_em_channel_b_energy
                state:
                  - Peak
            sequence:
              - action: input_number.set_value
                metadata: {}
                target:
                  entity_id: input_number.energy_tiered_price_current
                data:
                  value: 0.5533
              - parallel:
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Peak"'
                      name: sensor.main_line_em_channel_b_energy
                      entity_id: sensor.main_line_em_channel_b_energy
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Peak"'
                      name: input_datetime.tou_15_00_peak
                      entity_id: input_datetime.tou_15_00_peak
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Peak"'
                      name: select.tou_em_channel_b_energy
                      entity_id: select.tou_em_channel_b_energy
          - conditions:
              - condition: state
                entity_id: select.tou_em_channel_b_energy
                state:
                  - Super Off Peak
            sequence:
              - action: input_number.set_value
                metadata: {}
                target:
                  entity_id: input_number.energy_tiered_price_current
                data:
                  value: 0.0885
              - parallel:
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Super Off Peak"'
                      name: sensor.main_line_em_channel_b_energy
                      entity_id: sensor.main_line_em_channel_b_energy
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Super Off Peak"'
                      name: input_datetime.tou_09_00_super_off_peak
                      entity_id: input_datetime.tou_09_00_super_off_peak
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Super Off Peak"'
                      name: select.tou_em_channel_b_energy
                      entity_id: select.tou_em_channel_b_energy
          - conditions:
              - condition: state
                entity_id: select.tou_em_channel_b_energy
                state:
                  - Off Peak
            sequence:
              - action: input_number.set_value
                metadata: {}
                target:
                  entity_id: input_number.energy_tiered_price_current
                data:
                  value: 0.2434
              - parallel:
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Off Peak"'
                      name: sensor.main_line_em_channel_b_energy
                      entity_id: sensor.main_line_em_channel_b_energy
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Off Peak"'
                      name: input_datetime.tou_21_00_off_peak
                      entity_id: input_datetime.tou_21_00_off_peak
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Off Peak"'
                      name: input_datetime.tou_06_00_off_peak
                      entity_id: input_datetime.tou_06_00_off_peak
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Off Peak"'
                      name: select.tou_em_channel_b_energy
                      entity_id: select.tou_em_channel_b_energy
          - conditions:
              - condition: state
                entity_id: select.tou_em_channel_b_energy
                state:
                  - Overnight
            sequence:
              - action: input_number.set_value
                metadata: {}
                target:
                  entity_id: input_number.energy_tiered_price_current
                data:
                  value: 0.2434
              - parallel:
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Overnight"'
                      name: sensor.main_line_em_channel_b_energy
                      entity_id: sensor.main_line_em_channel_b_energy
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Overnight"'
                      name: input_datetime.tou_23_00_overnight
                      entity_id: input_datetime.tou_23_00_overnight
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: Select
                      message: 'Energy tariff: set rate for "Overnight"'
                      name: select.tou_em_channel_b_energy
                      entity_id: select.tou_em_channel_b_energy
mode: single

Renewables sub-routine: BESS discharge limit to actual max

alias: 'Renewables sub-routine: BESS discharge limit to actual max'
description: >-
  This routine overwrites some minor back-end errors with Fronius inverters on
  actual maximum charge/discharge. You can identify this in >2 mins from the 
  "Fronius reserva battery datasheet".


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454 
triggers:
  - trigger: numeric_state
    entity_id:
      - number.reserva_discharge_limit
    for:
      hours: 0
      minutes: 0
      seconds: 15
    above: 6760
conditions: []
actions:
  - parallel:
      - action: number.set_value
        metadata: {}
        target:
          entity_id: number.reserva_discharge_limit
        data:
          value: '6760'
      - action: logbook.log
        metadata: {}
        data:
          message: 'Renewables sub-routine: BESS discharge limit to actual max'
          entity_id: number.reserva_discharge_limit
          domain: Select
          name: number.reserva_discharge_limit
mode: single

Renewables sub-routine: BESS PV charge limit to actual max

alias: 'Renewables sub-routine: BESS PV charge limit to actual max'
description: >-
  This routine overwrites some minor back-end errors with Fronius inverters on
  actual maximum charge/discharge. You can identify this in >2 mins from the 
  "Fronius reserva battery datasheet".


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454 
triggers:
  - trigger: numeric_state
    entity_id:
      - number.reserva_pv_charge_limit
    for:
      hours: 0
      minutes: 0
      seconds: 18
    above: 6760
conditions: []
actions:
  - parallel:
      - action: number.set_value
        metadata: {}
        target:
          entity_id: number.reserva_pv_charge_limit
        data:
          value: '6760'
      - action: logbook.log
        metadata: {}
        data:
          message: 'Renewables sub-routine: BESS PV charge limit to actual max'
          entity_id: number.reserva_pv_charge_limit
          domain: Select
          name: number.reserva_pv_charge_limit
mode: single

Renewables routine, Energy Arbitrage: Cheap TOU (part 1/2) Solar-only

alias: 'Renewables routine, Energy Arbitrage: Cheap TOU (part 1/2) Solar-only'
description: >-
  This routine is to limit grid charge and enable solar charging of a BESS unit.


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454 
triggers:
  - trigger: state
    entity_id:
      - select.tou_em_channel_b_energy
    to:
      - Super Off Peak
    for:
      hours: 0
      minutes: 0
      seconds: 1
conditions: []
actions:
  - sequence:
      - sequence:
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_battery_api_mode
            data:
              option: Manual
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_storage_control_mode
            data:
              option: Charge from Grid
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_grid
            data: {}
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_ac
            data: {}
          - parallel:
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
                  entity_id: select.reserva_battery_api_mode
                  domain: Select
                  name: select.reserva_battery_api_mode
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
                  entity_id: select.reserva_storage_control_mode
                  domain: Select
                  name: select.reserva_storage_control_mode
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
                  entity_id: switch.reserva_charge_from_grid
                  domain: Select
                  name: switch.reserva_charge_from_grid
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
                  entity_id: switch.reserva_charge_from_ac
                  domain: Select
                  name: switch.reserva_charge_from_ac
      - sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: '0'
            target:
              entity_id: number.reserva_grid_charge_power
          - delay:
              hours: 0
              minutes: 0
              seconds: 15
              milliseconds: 0
          - action: number.set_value
            metadata: {}
            target:
              entity_id: number.reserva_target_feed_in
            data:
              value: '0'
          - delay:
              hours: 0
              minutes: 0
              seconds: 15
              milliseconds: 0
mode: single

Renewables routine, Energy Arbitrage: Cheap TOU (part 2/2) Solar + Grid

alias: 'Renewables routine, Energy Arbitrage: Cheap TOU (part 2/2) Solar + Grid'
description: |-
  This routine is to limit grid charge and enable solar charging of a BESS unit.

    Automation created by Benn, full documentation available on HA communities
    https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454 
triggers:
  - trigger: state
    entity_id:
      - select.tou_em_channel_b_energy
    to:
      - Super Off Peak
    for:
      hours: 3
      minutes: 0
      seconds: 1
conditions: []
actions:
  - sequence:
      - sequence:
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_battery_api_mode
            data:
              option: Manual
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_storage_control_mode
            data:
              option: Charge from Grid
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_grid
            data: {}
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_ac
            data: {}
          - parallel:
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 2 of 2 Solar+grid'
                  entity_id: select.reserva_battery_api_mode
                  domain: Select
                  name: select.reserva_battery_api_mode
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 2 of 2 Solar+grid'
                  entity_id: select.reserva_storage_control_mode
                  domain: Select
                  name: select.reserva_storage_control_mode
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 2 of 2 Solar+grid'
                  entity_id: switch.reserva_charge_from_grid
                  domain: Select
                  name: switch.reserva_charge_from_grid
              - action: logbook.log
                metadata: {}
                data:
                  message: 'Renewables routine: Cheap TOU part 2 of 2 Solar+grid'
                  entity_id: switch.reserva_charge_from_ac
                  domain: Select
                  name: switch.reserva_charge_from_ac
      - sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: '6700'
            target:
              entity_id: number.reserva_grid_charge_power
          - delay:
              hours: 0
              minutes: 0
              seconds: 15
              milliseconds: 0
          - action: number.set_value
            metadata: {}
            target:
              entity_id: number.reserva_target_feed_in
            data:
              value: '0'
          - delay:
              hours: 0
              minutes: 0
              seconds: 15
              milliseconds: 0
mode: single

Renewables routine, Energy Arbitrage: Expensive TOU - Peak Shaving ignore the grid

alias: 'Renewables routine, Energy Arbitrage: Expensive TOU - Peak Shaving ignore the grid'
description: >-
  This routine is to maximise "Peak Shaving"


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454 
triggers:
  - trigger: state
    entity_id:
      - select.tou_em_channel_b_energy
    to:
      - Peak
conditions: []
actions:
  - parallel:
      - action: select.select_option
        metadata: {}
        target:
          entity_id: select.reserva_battery_api_mode
        data:
          option: Auto
      - action: select.select_option
        metadata: {}
        target:
          entity_id: select.reserva_storage_control_mode
        data:
          option: PV Charge and Discharge Limit
      - action: switch.turn_on
        metadata: {}
        target:
          entity_id: switch.reserva_charge_from_ac
        data: {}
      - sequence:
          - delay:
              hours: 0
              minutes: 0
              seconds: 3
              milliseconds: 0
          - action: number.set_value
            metadata: {}
            target:
              entity_id: number.reserva_discharge_limit
            data:
              value: '6760'
          - action: number.set_value
            metadata: {}
            target:
              entity_id: number.reserva_pv_charge_limit
            data:
              value: '6760'
      - action: switch.turn_off
        metadata: {}
        target:
          entity_id: switch.reserva_charge_from_grid
        data: {}
      - parallel:
          - action: logbook.log
            metadata: {}
            data:
              message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
              entity_id: select.reserva_battery_api_mode
              domain: Select
              name: select.reserva_battery_api_mode
          - action: logbook.log
            metadata: {}
            data:
              message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
              entity_id: select.reserva_storage_control_mode
              domain: Select
              name: select.reserva_storage_control_mode
          - action: logbook.log
            metadata: {}
            data:
              message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
              entity_id: switch.reserva_charge_from_grid
              domain: Select
              name: switch.reserva_charge_from_grid
          - action: logbook.log
            metadata: {}
            data:
              message: 'Renewables routine: Cheap TOU part 1 of 2 Solar-only charge'
              entity_id: switch.reserva_charge_from_ac
              domain: Select
              name: switch.reserva_charge_from_ac
mode: single

Renewables routine, Grid Resilience: Shoulder TOU - Boost your battery (part1/2)

alias: 'Renewables routine, Grid Resilience: Shoulder TOU - Boost your battery (part1/2)'
description: >-
  This routine is for "Grid Resilience". This is an alternative to a static
  "minimum state of charge"; this is a 2-part process.

  1. Start: Charge your battery during a fairly cheap after-hours time until the
  goal % is reached. ~35% (This automation)

  2. End: Resume discharging using standard device settings


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454
triggers:
  - trigger: state
    entity_id:
      - select.tou_em_channel_b_energy
    from:
      - Off Peak
    to:
      - Overnight
conditions: []
actions:
  - sequence:
      - action: select.select_option
        metadata: {}
        target:
          entity_id: select.reserva_battery_api_mode
        data:
          option: Manual
      - delay:
          hours: 0
          minutes: 0
          seconds: 30
          milliseconds: 0
      - sequence:
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_grid
            data: {}
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_ac
            data: {}
          - delay:
              hours: 0
              minutes: 0
              seconds: 30
              milliseconds: 0
          - sequence:
              - action: select.select_option
                metadata: {}
                target:
                  entity_id: select.reserva_storage_control_mode
                data:
                  option: Charge from Grid
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 30
                  milliseconds: 0
              - sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: '3000'
                    target:
                      entity_id: number.reserva_grid_charge_power
                  - action: number.set_value
                    metadata: {}
                    target:
                      entity_id: number.reserva_pv_charge_limit
                    data:
                      value: '6760'
                  - action: number.set_value
                    metadata: {}
                    target:
                      entity_id: number.reserva_target_feed_in
                    data:
                      value: '0'
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: automation
                      message: >-
                        modbus automation to enable grid #Automation told me to
                        do it.
                      entity_id: sensor.reserva_state_of_charge
                  - action: logbook.log
                    metadata: {}
                    data:
                      domain: automation
                      entity_id: sensor.reserva_grid_charging
                      message: >-
                        modbus automation to enable grid #Automation told me to
                        do it.
mode: single

Renewables routine, Grid Resilience: Shoulder TOU - Boost your battery (part2/2)

alias: >-
  Renewables routine, Grid Resilience: Shoulder TOU - Boost your battery
  (part2/2)
description: >-
  This routine is for "Grid Resilience". This is an alternative to a static
  "minimum state of charge"; this is a 2-part process.

  1. Start: Charge your battery during a fairly cheap after-hours time until the
  goal % is reached. ~35%

  2. End: Resume discharging using standard device settings (This automation)


  Automation created by Benn, full documentation available on HA communities
  https://community.home-assistant.io/t/fronius-solar-bess-ev-charging/1025454
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.reserva_state_of_charge_2
    above: 35
conditions:
  - condition: select.is_option_selected
    target:
      entity_id: select.tou_em_channel_b_energy
    options:
      behavior: any
      for: '00:00:00'
      option:
        - Overnight
actions:
  - parallel:
      - sequence:
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_battery_api_mode
            data:
              option: Auto
          - action: logbook.log
            metadata: {}
            data:
              message: >-
                Renewables routine, Grid Resilience: Shoulder TOU - Boost your
                battery (part2/2)
              entity_id: select.reserva_battery_api_mode
              domain: Select
              name: select.reserva_battery_api_mode
      - sequence:
          - action: select.select_option
            metadata: {}
            target:
              entity_id: select.reserva_storage_control_mode
            data:
              option: Auto
          - action: logbook.log
            metadata: {}
            data:
              message: >-
                Renewables routine, Grid Resilience: Shoulder TOU - Boost your
                battery (part2/2)
              entity_id: switch.reserva_charge_from_grid
              domain: Select
              name: switch.reserva_charge_from_grid
      - sequence:
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_ac
            data: {}
          - action: logbook.log
            metadata: {}
            data:
              message: >-
                Renewables routine, Grid Resilience: Shoulder TOU - Boost your
                battery (part2/2)
              entity_id: switch.reserva_charge_from_ac
              domain: Select
              name: switch.reserva_charge_from_ac
      - sequence:
          - action: switch.turn_on
            metadata: {}
            target:
              entity_id: switch.reserva_charge_from_grid
            data: {}
          - action: logbook.log
            metadata: {}
            data:
              message: >-
                Renewables routine, Grid Resilience: Shoulder TOU - Boost your
                battery (part2/2)
              entity_id: select.reserva_storage_control_mode
              domain: Select
              name: select.reserva_storage_control_mode
mode: single