Page 2 of 2
Re: HA integration to control mode scheduler without modbus
Posted: Sat Jul 18, 2026 5:48 pm
by itm60
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
Posted: Sat Jul 18, 2026 5:55 pm
by Vini
Personally, I’d chat with ChatGPT.
I put what I wanted into Codex and now it runs my Solar via HA automations.
Re: HA integration to control mode scheduler without modbus
Posted: Sat Jul 18, 2026 6:17 pm
by itm60
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
Posted: Sat Jul 18, 2026 10:57 pm
by Vini
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