Re: HA integration to control mode scheduler without modbus
I'm currently having problems using FoxESS-Modbus with my KH7 inverter, and was wondering whether FoxESS-Control could solve my problems?
The problem with FoxESS-Modbus is: it can only put the inverter into one of three work modes:
- Self Use
- Back Up (when Back-Up or Force Charge is selected in FoxESS-Modbus)
- Feed-In Priority (when Feed-in First or Force Discharge is selected in FoxESS-Modbus)

The problem is that, due to the above limitations:
- If Force Charge (Back Up) mode is invoked when excess solar is being generated the excess solar is discarded - it is neither exported nor used to charge the battery
- If Force Discharge (Feed-In Priority) is selected it will not export charge from the battery to take advantage of good export rates unless feed-in limits have been exceeded. It will only export excess solar to the grid.

This means that I lose two major benefits of predbat:
- taking advantage of cheap/free/negative import rates to charge the battery during the day without discarding excess solar energy that is being generated at the time
- taking advantage of high export rates by exporting charge from the battery.
Could FoxESS-Control help with any of this?
Re: HA integration to control mode scheduler without modbus
Personally, I’d chat with ChatGPT.

I put what I wanted into Codex and now it runs my Solar via HA automations.
Fox 7kW HYBRID inverter with Fox EP11 10kWh battery
Re: HA integration to control mode scheduler without modbus
Would you be able to post an example of one of your automations, so that I can get an idea of the basic principles and methods?
Re: HA integration to control mode scheduler without modbus
itm60 wrote: Sat Jul 18, 2026 6:17 pm Would you be able to post an example of one of your automations, so that I can get an idea of the basic principles and methods?

Code: Select all

alias: Solar - Ohme EV Charging Guard
description: >-
  Clean-slate Ohme and solar-battery guard.


  Current intent:

  - Allow Ohme without approval during cheap Octopus/Intelligent periods or when
  genuine excess solar is available.

  - Require approval during expensive periods without excess solar.

  - Never allow the solar battery to discharge into the EV.

  - During cheap/Intelligent periods, block battery discharge only while Ohme is
  actively charging.

  - Let the battery discharge for normal house load at other times, including
  overnight.

  - Top the battery up late in the cheap window, then return to Self Use at
  05:30 or once SOC is above 90%.

  - Keep inverter SOC limits fixed at Min 10% and Max 100%.
triggers:
  - trigger: homeassistant
    event: start
    id: startup
  - trigger: time_pattern
    minutes: /1
    id: periodic_guard
  - trigger: time
    at: "23:30:00"
    id: fixed_offpeak_start
  - trigger: time
    at: "05:30:00"
    id: fixed_offpeak_end
  - trigger: state
    entity_id:
      - sensor.octopus_energy_electricity_2GUID_current_rate
      - >-
        binary_sensor.octopus_energy_0GUID_intelligent_dispatching
      - sensor.ohme_epod_status
      - sensor.ohme_epod_power
      - switch.garage_ohme_epod_solar_boost
      - switch.ohme_epod_require_approval
    id: state_changed
  - trigger: numeric_state
    entity_id: sensor.home_solar_feed_in
    above: 1.4
    for:
      minutes: 2
    id: excess_solar_available
  - trigger: numeric_state
    entity_id: sensor.home_solar_feed_in
    below: 0.35
    for:
      minutes: 1
    id: excess_solar_lost
  - trigger: numeric_state
    entity_id: sensor.home_solar_battery_discharge
    above: 0.05
    for:
      seconds: 15
    id: battery_discharge_guard
  - trigger: numeric_state
    entity_id: sensor.home_solar_grid_consumption
    above: 0.08
    for:
      minutes: 1
    id: grid_import_guard
  - trigger: state
    entity_id:
      - number.home_solar_min_soc
      - number.home_solar_min_soc_on_grid
      - number.home_solar_max_soc
      - number.home_solar_max_discharge_current
    id: inverter_setting_changed
  - trigger: time
    at: "03:30:00"
    id: late_topup_start
conditions: []
actions:
  - variables:
      rate: >-
        {{
        states('sensor.octopus_energy_electricity_2GUID_current_rate')
        | float(999) }}
      fixed_offpeak: >-
        {{ now().hour > 23 or (now().hour == 23 and now().minute >= 30) or
        now().hour < 5 or (now().hour == 5 and now().minute < 30) }}
      cheap_rate: >-
        {{
        states('sensor.octopus_energy_electricity_2GUID_current_rate')
        | float(999) < 0.08 }}
      intelligent_slot: >-
        {{
        is_state('binary_sensor.octopus_energy_0GUID_intelligent_dispatching',
        'on') or
        state_attr('sensor.octopus_energy_electricity_2GUID_current_rate',
        'is_intelligent_adjusted') == true }}
      cheap_or_intelligent: "{{ cheap_rate or intelligent_slot or fixed_offpeak }}"
      excess_solar: "{{ states('sensor.home_solar_feed_in') | float(0) >= 1.4 }}"
      ev_charging: >-
        {{ states('sensor.ohme_epod_status') == 'charging' or
        states('sensor.ohme_epod_power') | float(0) > 0.2 }}
      ev_ready: >-
        {{ states('sensor.ohme_epod_status') in ['charging', 'plugged_in',
        'pending_approval'] }}
      battery_discharge: "{{ states('sensor.home_solar_battery_discharge') | float(0) }}"
      grid_import: "{{ states('sensor.home_solar_grid_consumption') | float(0) }}"
      ohme_mode: "{{ states('select.ohme_epod_charge_mode') }}"
      allowed_without_approval: "{{ cheap_or_intelligent or excess_solar }}"
      battery_soc: "{{ states('sensor.home_solar_battery_soc') | float(0) }}"
      late_topup_window: >-
        {{ (now().hour == 3 and now().minute >= 30) or now().hour == 4 or
        (now().hour == 5 and now().minute < 30) }}
  - choose:
      - alias: Keep Min SoC at 10 if too high
        conditions:
          - condition: numeric_state
            entity_id: number.home_solar_min_soc
            above: 10
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_min_soc
            data:
              value: 10
      - alias: Keep Min SoC at 10 if too low
        conditions:
          - condition: numeric_state
            entity_id: number.home_solar_min_soc
            below: 10
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_min_soc
            data:
              value: 10
    default: []
  - choose:
      - alias: Keep Min SoC on Grid at 10 if too high
        conditions:
          - condition: numeric_state
            entity_id: number.home_solar_min_soc_on_grid
            above: 10
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_min_soc_on_grid
            data:
              value: 10
      - alias: Keep Min SoC on Grid at 10 if too low
        conditions:
          - condition: numeric_state
            entity_id: number.home_solar_min_soc_on_grid
            below: 10
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_min_soc_on_grid
            data:
              value: 10
    default: []
  - choose:
      - alias: Keep Max SoC at 100
        conditions:
          - condition: numeric_state
            entity_id: number.home_solar_max_soc
            below: 100
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_max_soc
            data:
              value: 100
    default: []
  - alias: Late cheap-window battery top-up control
    choose:
      - alias: Return battery to Self Use above 90% or when cheap window ends
        conditions:
          - condition: or
            conditions:
              - condition: trigger
                id: fixed_offpeak_end
              - condition: and
                conditions:
                  - condition: time
                    after: "03:30:00"
                    before: "05:30:00"
                  - condition: numeric_state
                    entity_id: sensor.home_solar_battery_soc
                    above: 90
        sequence:
          - action: select.select_option
            target:
              entity_id: select.home_solar_work_mode
            data:
              option: Self Use
      - alias: Late cheap-window top-up until SOC is above 90%
        conditions:
          - condition: time
            after: "03:30:00"
            before: "05:30:00"
          - condition: numeric_state
            entity_id: sensor.home_solar_battery_soc
            below: 90
          - condition: template
            value_template: "{{ cheap_or_intelligent }}"
        sequence:
          - action: number.set_value
            target:
              entity_id: number.home_solar_max_soc
            data:
              value: 100
          - action: number.set_value
            target:
              entity_id: number.home_solar_max_charge_current
            data:
              value: 50
          - action: select.select_option
            target:
              entity_id: select.home_solar_work_mode
            data:
              option: Force Charge
    default: []
  - choose:
      - alias: >-
          Cheap/Intelligent EV availability: allow Ohme, block battery only
          while actively charging
        conditions:
          - condition: template
            value_template: "{{ cheap_or_intelligent and ev_ready }}"
        sequence:
          - action: switch.turn_off
            target:
              entity_id: switch.ohme_epod_require_approval
          - action: switch.turn_on
            target:
              entity_id: switch.garage_ohme_epod_solar_boost
          - choose:
              - alias: Resume Ohme if paused in cheap/Intelligent period
                conditions:
                  - condition: state
                    entity_id: select.ohme_epod_charge_mode
                    state: paused
                sequence:
                  - action: select.select_option
                    target:
                      entity_id: select.ohme_epod_charge_mode
                    data:
                      option: smart_charge
            default: []
          - choose:
              - alias: Clamp battery discharge only while Ohme is actively charging
                conditions:
                  - condition: template
                    value_template: "{{ ev_charging }}"
                  - condition: numeric_state
                    entity_id: number.home_solar_max_discharge_current
                    above: 0
                sequence:
                  - action: number.set_value
                    target:
                      entity_id: number.home_solar_max_discharge_current
                    data:
                      value: 0
              - alias: Release battery discharge when Ohme is not actively charging
                conditions:
                  - condition: template
                    value_template: "{{ not ev_charging }}"
                  - condition: numeric_state
                    entity_id: number.home_solar_max_discharge_current
                    below: 25
                sequence:
                  - action: number.set_value
                    target:
                      entity_id: number.home_solar_max_discharge_current
                    data:
                      value: 25
            default: []
      - alias: >-
          Expensive with excess solar: allow Ohme without approval, keep battery
          available
        conditions:
          - condition: template
            value_template: "{{ not cheap_or_intelligent and excess_solar and ev_ready }}"
        sequence:
          - choose:
              - alias: Pause Ohme if solar charging starts using battery or grid
                conditions:
                  - condition: template
                    value_template: >-
                      {{ ev_charging and (battery_discharge > 0.05 or
                      grid_import > 0.08 or (trigger is defined and trigger.id
                      in ['battery_discharge_guard', 'grid_import_guard'])) }}
                sequence:
                  - action: select.select_option
                    target:
                      entity_id: select.ohme_epod_charge_mode
                    data:
                      option: paused
                  - action: persistent_notification.create
                    data:
                      title: Ohme charging paused
                      message: "Ohme paused: battery/grid detected."
                      notification_id: SolarOhmeGuardPaused
              - alias: Allow Ohme on genuine excess solar
                conditions:
                  - condition: template
                    value_template: >-
                      {{ not (ev_charging and (battery_discharge > 0.05 or
                      grid_import > 0.08)) }}
                sequence:
                  - action: switch.turn_off
                    target:
                      entity_id: switch.ohme_epod_require_approval
                  - action: switch.turn_on
                    target:
                      entity_id: switch.garage_ohme_epod_solar_boost
                  - choose:
                      - alias: Resume Ohme for solar charging
                        conditions:
                          - condition: state
                            entity_id: select.ohme_epod_charge_mode
                            state: paused
                        sequence:
                          - action: select.select_option
                            target:
                              entity_id: select.ohme_epod_charge_mode
                            data:
                              option: smart_charge
                    default: []
                  - choose:
                      - alias: >-
                          Release battery discharge for house load during
                          expensive solar charging
                        conditions:
                          - condition: numeric_state
                            entity_id: number.home_solar_max_discharge_current
                            below: 25
                        sequence:
                          - action: number.set_value
                            target:
                              entity_id: number.home_solar_max_discharge_current
                            data:
                              value: 25
                    default: []
            default: []
      - alias: >-
          Expensive without excess solar: require approval and keep house
          battery available
        conditions:
          - condition: template
            value_template: "{{ not cheap_or_intelligent and not excess_solar }}"
        sequence:
          - action: switch.turn_on
            target:
              entity_id: switch.ohme_epod_require_approval
          - choose:
              - alias: Release battery discharge for house load during expensive rate
                conditions:
                  - condition: numeric_state
                    entity_id: number.home_solar_max_discharge_current
                    below: 25
                sequence:
                  - action: number.set_value
                    target:
                      entity_id: number.home_solar_max_discharge_current
                    data:
                      value: 25
            default: []
          - choose:
              - alias: >-
                  Pause Ohme if it is charging during expensive rate without
                  solar cover
                conditions:
                  - condition: template
                    value_template: >-
                      {{ ev_charging and (battery_discharge > 0.05 or
                      grid_import > 0.08 or (trigger is defined and trigger.id
                      in ['battery_discharge_guard', 'grid_import_guard'])) }}
                sequence:
                  - action: select.select_option
                    target:
                      entity_id: select.ohme_epod_charge_mode
                    data:
                      option: paused
                  - action: persistent_notification.create
                    data:
                      title: Ohme charging paused
                      message: "Ohme paused: expensive rate and no excess solar."
                      notification_id: SolarOhmeGuardPaused
            default: []
    default:
      - choose:
          - alias: "No EV ready: keep battery available"
            conditions:
              - condition: numeric_state
                entity_id: number.home_solar_max_discharge_current
                below: 25
            sequence:
              - action: number.set_value
                target:
                  entity_id: number.home_solar_max_discharge_current
                data:
                  value: 25
        default: []
mode: restart
Fox 7kW HYBRID inverter with Fox EP11 10kWh battery
Post Reply