Skip to content

Instantly share code, notes, and snippets.

@xrad
Created April 9, 2025 18:55
Show Gist options
  • Save xrad/4194e4fa61b61cb4d0d94e56a537611a to your computer and use it in GitHub Desktop.
Save xrad/4194e4fa61b61cb4d0d94e56a537611a to your computer and use it in GitHub Desktop.
Determine a recommended FoxESS work mode to shift battery charging to a later point in the day. This is good for the battery life as well as it assists power providers by taking away feed-in during peak times.
{% set options = state_attr('select.h3_work_mode', "options") %}
{% set opt_self_use = options[0] %}
{% set opt_feed_in = options[1] %}
{# default to self-use #}
{% set recommended_work_mode = opt_self_use %}
{% set pv_power = states('sensor.pv_power_h3') | float(0) %}
{% set pv_energy_expected = states('sensor.solcast_pv_forecast_prognose_verbleibende_leistung_heute') | float(0) %}
{# require at least some current and expected PV power #}
{# TODO - enhance to select backup during night based on forecast #}
{% if pv_power|round(1) >= 0.5 and pv_energy_expected > 20 %}
{% if pv_energy_expected > 30 %}
{% set safe_soc_percent = 40 %}
{% elif pv_energy_expected > 25 %}
{% set safe_soc_percent = 60 %}
{% else %}
{% set safe_soc_percent = 80 %}
{% endif %}
{% set soc = states('sensor.h3_battery_soc') | float(default=0) %}
{% if soc < safe_soc_percent %}
{# always ensure a 40% charge #}
{% set recommended_work_mode = opt_self_use %}
{% else %}
{# fetch relevant times and convert to comparable numbers #}
{% set peak_time = as_timestamp(states('sensor.solcast_pv_forecast_zeitpunkt_spitzenleistung_heute')) %}
{% set current_time = as_timestamp(utcnow()) %}
{% set peak_time_reached = current_time > peak_time %}
{# estimate energy needed to charge battery including a ~ 20 % charging loss #}
{% set bat_charging_capacity = states('sensor.bat_charging_capacity') | float(0) %}
{% set total_energy_required = min(bat_charging_capacity * 1.25, bat_charging_capacity + 2.0) %}
{# estimate remaining energy including a ~ 20 % safety margin #}
{% set pv_energy_expected_net = pv_energy_expected * 0.8 %}
{% set sufficient_energy_left = total_energy_required < pv_energy_expected_net %}
{% if peak_time_reached or not sufficient_energy_left %}
{% set recommended_work_mode = opt_self_use %}
{% else %}
{% set recommended_work_mode = opt_feed_in %}
{% endif %}
{% endif %}
{% endif %}
{{recommended_work_mode}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment