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
Re: HA integration to control mode scheduler without modbus
I applied Master 1.59 and Manager 1.78 to my system (H1-5.0-E-G2) a couple of days ago, and it appears to have resolved an issue i was having with this Home Assistant integration. Obviously, with no idea of what has actually changed, I can't say what was wrong or what was fixed :shock:
Re: HA integration to control mode scheduler without modbus
This looks really amazing and exactly like what I need without spending too much time on integrating Modbus (using the battery in the winter months for charging during low cost windows in the night).

Could you maybe clarify the option "Battery Capacity" for me? Is that the nominal capacity? Or the usable capacity between minimum and maximum SOC? Do I need to apply degradation due to the SOH? Thanks a lot again, I absolutely love your work.
Post Reply