Created
November 19, 2025 18:44
-
-
Save ALERTua/62fb3baa524195f6b7971b330a5400d5 to your computer and use it in GitHub Desktop.
Dynamic Ecoflow charging speed according to the time left until the next power outage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {% set debug = false %} | |
| {# ==== CONFIGURATION ==== #} | |
| {% set charging_speed_eid = 'number.delta_pro_api_ac_charging_power' %} | |
| {% set main_capacity_eid = 'sensor.delta_pro_api_main_remain_capacity' %} | |
| {% set slave_capacity_eid = 'sensor.delta_pro_api_slave_1_remain_capacity' %} | |
| {% set battery_level_eid = 'sensor.delta_pro_api_battery_level' %} | |
| {% set target_battery_level_eid = 'number.delta_pro_api_max_charge_level' %} | |
| {% set next_outage_eid = 'sensor.kiiv_dtek_3_1_next_planned_outage' %} | |
| {% set battery_voltage = 51 %} | |
| {% set nominal_capacity_mah = 80000 %} | |
| {% set mah_to_wh = battery_voltage / 1000 %} | |
| {% set nominal_capacity_wh = nominal_capacity_mah * mah_to_wh * 2 %} | |
| {% set charging_speed_limit = 1800 %} | |
| {% set charge_margin_pct = 0 %} | |
| {% set charge_margin_min = 15 %} | |
| {# ==== LIVE DATA ==== #} | |
| {% set main_capacity = states(main_capacity_eid) | float(0) %} | |
| {% set slave_capacity = states(slave_capacity_eid) | float(0) %} | |
| {% set measured_capacity_wh = (main_capacity + slave_capacity) * mah_to_wh %} | |
| {% set battery_level = states(battery_level_eid) | float(0) %} | |
| {% set target_level = states(target_battery_level_eid) | float(100) %} | |
| {% set charging_speed_now = states(charging_speed_eid) | float(0) %} | |
| {% set step = state_attr(charging_speed_eid, 'step') | float(1) %} | |
| {% set speed_max = state_attr(charging_speed_eid, 'max') | float(0) %} | |
| {% set speed_min = state_attr(charging_speed_eid, 'min') | float(0) %} | |
| {% set next_outage = states(next_outage_eid) | as_datetime %} | |
| {# ==== ESTIMATE CHARGE TIME ==== #} | |
| {% if battery_level < target_level %} | |
| {% set energy_needed = (target_level - battery_level) / 100 * nominal_capacity_wh %} | |
| {% set assumed_speed = [speed_max, charging_speed_limit] | min %} | |
| {% set minutes_until_charged = (energy_needed / assumed_speed * 60) | int %} | |
| {% else %} | |
| {% set minutes_until_charged = 0 %} | |
| {% set energy_needed = 0 %} | |
| {% set assumed_speed = 0 %} | |
| {% endif %} | |
| {# ==== CALCULATE TIME TO OUTAGE ==== #} | |
| {% if next_outage %} | |
| {% set minutes_until_outage = ((next_outage - now()).total_seconds() / 60) | int %} | |
| {% set minutes_until_outage = [minutes_until_outage, 0] | max %} | |
| {% else %} | |
| {% set minutes_until_outage = 0 %} | |
| {% endif %} | |
| {# ==== CALCULATE EFFECTIVE SPEED ==== #} | |
| {% if minutes_until_outage > 0 and minutes_until_charged > 0 %} | |
| {% set effective_outage_time = minutes_until_outage * (1 - charge_margin_pct / 100) - charge_margin_min %} | |
| {% set effective_outage_time = [effective_outage_time, 1] | max %} | |
| {# --- Compute required power --- #} | |
| {% set required_power = (energy_needed * 60.0 / effective_outage_time) %} | |
| {# --- Safety margin --- #} | |
| {% set required_power = required_power * 1.05 %} | |
| {# --- Round up to nearest step --- #} | |
| {% set raw_speed = ((required_power + step - 1) / step) | int * step %} | |
| {# --- Clamp to limits --- #} | |
| {% set speed = [raw_speed, speed_max, charging_speed_limit] | min %} | |
| {% set speed = [speed, speed_min] | max %} | |
| {% else %} | |
| {% set speed = speed_min %} | |
| {% set raw_speed = 0 %} | |
| {% set required_power = 0 %} | |
| {% set effective_outage_time = 0 %} | |
| {% endif %} | |
| {# ==== ESTIMATE TIME @ RECOMMENDED SPEED ==== #} | |
| {% if speed > 0 %} | |
| {% set estimated_time_at_speed = (energy_needed / speed * 60) | int %} | |
| {% else %} | |
| {% set estimated_time_at_speed = 0 %} | |
| {% endif %} | |
| {# ==== DEBUG ==== #} | |
| {% if debug %} | |
| {% set lines = [ | |
| "🔧 **DEBUG MODE**", | |
| "----------------", | |
| "Main cap (mAh): " ~ main_capacity, | |
| "Slave cap (mAh): " ~ slave_capacity, | |
| "Measured total (Wh): " ~ (measured_capacity_wh | round(1)), | |
| "Nominal total (Wh): " ~ (nominal_capacity_wh | round(1)), | |
| "Battery level: " ~ battery_level ~ "%", | |
| "Target level: " ~ target_level ~ "%", | |
| "Energy needed (Wh): " ~ (energy_needed | round(1)), | |
| "Assumed speed (W): " ~ assumed_speed, | |
| "Estimated time @ assumed speed: " ~ minutes_until_charged ~ " min", | |
| "Next outage: " ~ (next_outage if next_outage else "none"), | |
| "Minutes until outage: " ~ minutes_until_outage, | |
| "Effective outage time (min): " ~ effective_outage_time, | |
| "Required power (no rounding): " ~ (required_power | round(1)), | |
| "Step size (W): " ~ step, | |
| "Raw speed (stepped): " ~ raw_speed, | |
| "Estimated time @ recommended speed: " ~ estimated_time_at_speed ~ " min", | |
| "Speed limits: min=" ~ speed_min ~ ", max=" ~ speed_max ~ ", limit=" ~ charging_speed_limit, | |
| "----------------", | |
| ("⚠️ WARNING: Target cannot be reached in time!" if estimated_time_at_speed > effective_outage_time else "✅ Within outage window"), | |
| "----------------", | |
| "✅ Final recommended speed: " ~ (speed | int) ~ " W" | |
| ] %} | |
| {{ lines | join('\n') }} | |
| {% else %} | |
| {{ speed | int }} | |
| {% endif %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment