EP11 (LiFePo4) best SoC range for longevity?
Hi,

Does anyone have any studies, reports on how the longevity of LiFePo4 batteries is affected by different ranges being used?

e.g. for longevity, is
0-100%
20-100%
0-80%
20-80%

best, and by how much?

A lot of people seem to have opinions on this but was wondering does anyone know of any proper research here?

Many thanks,

Mark
Re: EP11 (LiFePo4) best SoC range for longevity?
There are a lot of research papers about for LFP batteries but they tend to focus on specific things like ageing, or temperature - the main problem being that LFP batteries do not have enough historical data to study as the chemistry is fairly new.

This is a very good video that explains some of the realities



The main thing to remember is that Fox have already limited the batteries to 90% DOD and they provide warranties for their batteries being charged by their BMS systems which do require regular 100% charge cycles to maintain SoC accuracy. Best advice is to use them within the Fox specifications temperature, currents and their battery warranty will provide all the guarantees you need.
Re: EP11 (LiFePo4) best SoC range for longevity?
Thanks Dave!

That makes sense!

when you say:

"which do require regular 100% charge cycles to maintain SoC accuracy"

Any ideas how often 'regular' is?
1x per month
1x per week
1x per day?
Re: EP11 (LiFePo4) best SoC range for longevity?
It’s best to do it monthly, it won’t damage them if you don’t but you’ll see the accuracy of the SoC gets worse with occasional jumps as it re-evaluates the Soc from the cell voltages.
Re: EP11 (LiFePo4) best SoC range for longevity?
I found this one quite interesting

https://iopscience.iop.org/article/10.1 ... 111/ad6cbd

There's also https://www.sciencedirect.com/science/a ... 1722000283 and https://www.mdpi.com/1996-1073/14/6/1732 which cover aspects like calendar degradation.

Personally I do 100% once a week, 10% once a month via an automation. It'll do it more often in certain circumstances (for example, if forecast PV for the day is very low, it'll use the full range instead for a bit of extra arbitrage to make up for the lost generation).

It's not worth doing the calibration cycles manually, you might as well just stick to the full range rather than trying to keep track. Also, underutilising the battery is just as much of a waste, due to calendar degradation (for example, sticking to 20-80 all the time, 0.6 full cycles daily, would mean you'd run out of warranty years, and the battery capacity would have decreased anyway due to the passing of time). It's a bit of a balancing act.

Calendar degradation is (relative to cycling) more important on LFP, whereas with NMC batteries the cycling is a much bigger factor.
Re: EP11 (LiFePo4) best SoC range for longevity?
Thanks WyndStryke for your thoughtful reply (and for the papers), much appreciated! 😊

What SoC range do you typically use for your batteries then?

WyndStryke wrote: Mon Aug 04, 2025 5:56 pm
Re: EP11 (LiFePo4) best SoC range for longevity?
What SoC range do you typically use for your batteries then?
It changes on a day to day basis, anywhere from 14-92 to 20-84 (my automations will tweak it based on the PV forecast / weather forecast / etc), but I will also be cycling in the middle of that range as well (again, dependant on things like cell temperature / PV / weather / etc). I also adjust charge and discharge rates based on those criteria. On very hot days etc it will be using the slowest possible charge and discharge rate and no mid-range cycling (a high cell temperature causes increased cell degradation). When it is cold, it will be more aggressive, to generate warmth.


So I'm using more like 0.8-1.0 full cycles daily even if I don't hit the extremes. That's only possible on particular tariffs.
schedule.png
Re: EP11 (LiFePo4) best SoC range for longevity?
I would honestly expect FoxESS to manage this properly. The only thing as a enduser I should set is the MinimumSoC and the rest the system should "automagically" manage.
🏡 System Setup (Austria): Inverter: STAR-H3-12.0-E / Battery: STAR EP11 (10.36 kWh) / Panels: 24x Canadian HiHero 440 Wp (10.56 kWp total)
Re: EP11 (LiFePo4) best SoC range for longevity?
That's how 95% of people do it. I tend to go above&beyond. The BMS will already reduce the charge rate as you near 100%, or if the battery is very hot or cold. I just put stronger limits on things.
Re: EP11 (LiFePo4) best SoC range for longevity?
Hi All.

I have an EP11, installed during February as part of a new solar install (Fox 6kW hybrid inverter, for what it's worth).

I have set the SoC to 15% (I think it was at 20% by default) and allow it to charge up to 100%, which over the first six months it has done so more than 50% (maybe as much as 80% plus) of days - though winter is of course coming ;)

I don't do forced charging or discharging - I just let it fluctuate up and down according to solar availability and our usage. During the hot nights, it goes down to 15% due to air con and fan usage.

Is this basically fine and an OK operating mode for this battery?

Ian C
Re: EP11 (LiFePo4) best SoC range for longevity?
Yes it's fine, the important thing is that it gets to 100% from time to time as it's in the last few % the batteries balance all of which will improve the accuracy of the batteries SoC reading.

In winter it's likely you won't get anywhere near 100% some people use the eco tariff's (EV or eco 7) to charge during the night on the low tariff and then use the power during the day when the tariffs are high. If you don't do that you might want to give it a monthly charge from grid to 100% just to keep it reporting accurately.

Equally you can set the battery minSoC to 10%, it is rated for that and it won't effect the warranty or guarantees plus you'll get all the capacity you have paid for - the only time it might be better to be at 15% is when it is very cold over winter, particularly if the batteries are stored externally (and don't have the internal heater option).
Re: EP11 (LiFePo4) best SoC range for longevity?
Thanks, Dave.

Interestingly, I had a look at the behaviour in February.

Feed in to the grid occurred at some point on the following dates after the mid-Feb install (implying the battery was full): 14th, 15th, 17th, 18th, 19th, 21st, 22nd, 23rd, 24th, 25th, 26th, 27th, 28th (or perhaps more simply, not the 16th and the 20th). I've got an array of panels matching the hybrid inverter capacity facing 5-10 degrees west of south without obstruction, so even in winter, it was producing decently.

Half or more of these were only for short periods around the middle of the day. I suppose this might mean that the battery couldn't handle all the hybrid inverter's spot output on a bright day, so the excess was diverted to the grid - in which case the battery was probably not full. However, a number of days did have sustained periods of feed in, with the usual arc starting in the middle of the day then decreasing through to sunset - in which case the battery probably was full.

So, even with a few of those during bright winter days pushing the battery to 100%, all should be good without me needing to do anything, if I've understood you correctly.

Ian C
Re: EP11 (LiFePo4) best SoC range for longevity?
Ok no problem, keep an eye on it - it’s not essential and if it doesn’t hit 100% for a few months you just might start to see jumps in SoC and drifts in accuracy but theres no damage as a result.

Just as a quick FYI December is by far the worst solar month, followed by January, February is a big improvement
Re: EP11 (LiFePo4) best SoC range for longevity?
July felt like it was bad (compared to the sunny weather earlier in the year), but I was still 9% above the PVGis and installer estimates despite the seemingly endless cloud cover. That really surprised me.
Re: EP11 (LiFePo4) best SoC range for longevity?
Hi all,

I just got my system installed, and I have the opposite problem as everyone on this post here so I'm looking for some advice.

I have the H1(g2) 6kw inverter installed with 6.6kw PV system with 2x ep11 (20.72kw) battery. I live in australia so doesn't matter if it's winter or summer, my battery will sit at 100% for almost the entirety of the day anywhere from about 11am till about 7pm (when i return from work). I'm at the point where I'm constantly trying to force the use of central cooling/heating at night just to use the stored energy.

What would the best recommendation be in terms of battery longetivity? I've been reading mixed reviews about batteries in general and how it shouldn't be left at 100% for long periods. Since installation, my SoC has never even seen anything under 50%.

Would setting something like this work? Since my battery is 100% around 11am, i'm thinking of setting a forced discharge to 85% from 11am - 7pm (which is when i return from work)?

Am I overthinking?
User avatar
Site Admin
Re: EP11 (LiFePo4) best SoC range for longevity?
I would once a month do a force discharge down to 10% SoC and allow the system to slowly charge again to full. Don't worry about holding it at 100% as these are LFP cells and are happy and stable to sit at 100% for months. Unlike NMC or NCA cells which are damaged with prolonged max soc holding.

knightwalkr wrote: Sat Sep 06, 2025 10:54 am Hi all,

I just got my system installed, and I have the opposite problem as everyone on this post here so I'm looking for some advice.

I have the H1(g2) 6kw inverter installed with 6.6kw PV system with 2x ep11 (20.72kw) battery. I live in australia so doesn't matter if it's winter or summer, my battery will sit at 100% for almost the entirety of the day anywhere from about 11am till about 7pm (when i return from work). I'm at the point where I'm constantly trying to force the use of central cooling/heating at night just to use the stored energy.

What would the best recommendation be in terms of battery longetivity? I've been reading mixed reviews about batteries in general and how it shouldn't be left at 100% for long periods. Since installation, my SoC has never even seen anything under 50%.

Would setting something like this work? Since my battery is 100% around 11am, i'm thinking of setting a forced discharge to 85% from 11am - 7pm (which is when i return from work)?

Am I overthinking?
Community Admin / FoxESS Elite Professional

Image Did I help you? Feel free to leave me a tip
Image Book a zoom meeting for remote consultancy or help
Image Switch to Octopus and earn £50
Image Get a heatpump from Octopus and earn £100
Image Subscribe to my YouTube channel

Fox ESS Tri Inverter Installation
2 x KH Hybird Inverters (Parallel Mode)
1 x H1 Gen1
24 x HV2600 (62.4kWh)
32 x 490w across 4 arrays
Dual Tesla Household
Heatpump & Low Carbon Housebuild
Re: EP11 (LiFePo4) best SoC range for longevity?
WyndStryke wrote: Mon Aug 04, 2025 5:56 pm
Personally I do 100% once a week, 10% once a month via an automation.
Hi WyndStryke
It looks like you are using home assistant for the automation. If that is the case, do you mind sharing your code for your automations? I just got me solar/battery installed and hooked it up to my HA server via modbus. I'm keen to do some good battery management.
Thanks
Alan
Re: EP11 (LiFePo4) best SoC range for longevity?
You're probably best off writing your own, I was just learning how to write automations, wouldn't do it the same way now. There are over 20 interacting automations, and maybe 140 helpers, but these are the main ones which would be involved with calibration.

Code: Select all


alias: FoxESS calibrate set bottom SoC reached
description: >-
  When the battery SoC drops to the minimum, it means that the BMS will be able
  to calibrate the low end of the SoC voltage range.  Store the date so that we
  can use it to schedule the next calibration cycle.
triggers:
  - trigger: template
    value_template: >-
      {{(states('sensor.battery_soc')| float) <=
      (states('input_number.foxess_calibrate_bottom_soc')| float)}}
  - trigger: state
    entity_id:
      - sensor.battery_soc
  - trigger: time_pattern
    minutes: /10
    seconds: "15"
conditions:
  - condition: template
    value_template: >-
      {{(states('sensor.battery_soc')| float) <=
      (states('input_number.foxess_calibrate_bottom_soc')| float)}}
actions:
  - action: input_datetime.set_datetime
    metadata: {}
    data:
      datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
    target:
      entity_id: input_datetime.foxess_calibrate_bottom_reached_date
  - action: input_boolean.turn_on
    metadata: {}
    data: {}
    target:
      entity_id: input_boolean.foxess_calibrate_bottom_reached
  - action: input_text.set_value
    metadata: {}
    data:
      value: Bottom SoC reached
    target:
      entity_id: input_text.foxess_schedule_mode
  - choose:
      - conditions:
          - condition: state
            entity_id: input_boolean.foxess_calibrate_top_reached
            state: "on"
          - condition: state
            entity_id: input_boolean.foxess_calibrate_bottom_reached
            state: "on"
          - condition: state
            entity_id: input_boolean.foxess_calibrate_today
            state: "on"
        sequence:
          - action: input_boolean.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: input_boolean.foxess_calibrate_today
mode: single

Code: Select all

alias: FoxESS calibrate set top SoC reached
description: >-
  When the battery SoC hits the max, it means that the BMS will be able to
  calibrate the high end of the SoC voltage range.  Store the date so that we
  can use it to schedule the next calibration cycle.   Note that it may take
  multiple calibration cycles to resolve if SoC calibration has been fully lost.
triggers:
  - trigger: state
    entity_id:
      - sensor.battery_soc
  - trigger: template
    value_template: >-
      {{ (states('sensor.battery_soc') | float) >=
      (states('input_number.FoxESS_calibrate_top_SoC') | float) }}
  - trigger: time_pattern
    minutes: /10
    seconds: "15"
conditions:
  - condition: template
    value_template: >-
      {{ (states('sensor.battery_soc') | float) >=
      (states('input_number.FoxESS_calibrate_top_SoC') | float) }}
actions:
  - if:
      - condition: or
        conditions:
          - condition: state
            entity_id: input_boolean.foxess_calibrate_top_reached
            state: "off"
          - condition: template
            value_template: >-
              {{
              (states('input_datetime.foxess_calibrate_top_reached_date')|as_datetime).date()
              <= (now()-timedelta(days=1)).date() }}              
    then:
      - action: input_datetime.set_datetime
        metadata: {}
        data:
          datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
        target:
          entity_id: input_datetime.foxess_calibrate_top_reached_date
      - action: input_boolean.turn_on
        metadata: {}
        data: {}
        target:
          entity_id: input_boolean.foxess_calibrate_top_reached
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
      - action: input_text.set_value
        metadata: {}
        data:
          value: Top SoC reached
        target:
          entity_id: input_text.foxess_schedule_mode
  - choose:
      - conditions:
          - condition: state
            entity_id: input_boolean.foxess_calibrate_top_reached
            state: "on"
          - condition: state
            state: "on"
            entity_id: input_boolean.foxess_calibrate_bottom_reached
          - condition: state
            entity_id: input_boolean.foxess_calibrate_today
            state: "on"
        sequence:
          - action: input_boolean.turn_off
            metadata: {}
            data: {}
            target:
              entity_id: input_boolean.foxess_calibrate_today
mode: single



Code: Select all

alias: FoxESS Overnight charge/discharge speed
description: ""
triggers:
  - trigger: state
    entity_id:
      - input_boolean.foxess_calibrate_top_reached
      - sensor.battery_soc
  - trigger: state
    entity_id:
      - sensor.FoxESS_overnight_charge_rate_kW
      - sensor.FoxESS_overnight_discharge_rate_kW
      - select.work_mode
      - input_boolean.eon_next_drive_cheap_period
      - input_number.foxess_overnight_calibration_modifier
    for:
      hours: 0
      minutes: 0
      seconds: 1
  - trigger: time
    at: "00:00:05"
  - trigger: time
    at: "00:02:05"
  - trigger: time
    at: "06:30:05"
  - trigger: time
    at: "06:45:05"
  - trigger: time
    at: "06:58:05"
conditions:
  - condition: state
    entity_id: input_boolean.eon_next_drive_cheap_period
    state: "on"
actions:
  - if:
      - condition: state
        entity_id: input_boolean.foxess_calibrate_top_reached
        state: "off"
    then:
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1.1
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
    else:
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
    enabled: false
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: time
                after: "00:00:00"
                before: "00:01:59"
              - condition: time
                after: "06:58:00"
                before: "07:00:00"
              - condition: template
                value_template: >-
                  {% set target_soc = 
                  states('input_number.foxess_calibrate_top_soc') | float %} {%
                  if states('input_boolean.foxess_calibrate_top_reached') | bool
                  %}
                    {% set target_soc = states('input_number.foxess_overnight_charge_top_soc') | float %}
                  {% endif %} {{states('sensor.battery_soc') | float >=
                  target_soc}}
        sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: "0.4"
            target:
              entity_id: number.force_charge_power
          - action: number.set_value
            metadata: {}
            data:
              value: "{{(states('sensor.pv_power')| float) + 0.1}}"
            target:
              entity_id: number.force_discharge_power
      - conditions:
          - condition: time
            after: "00:02:00"
            before: "06:58:00"
          - condition: numeric_state
            entity_id: sensor.battery_soc
            above: 90
        sequence:
          - if:
              - condition: state
                entity_id: select.work_mode
                state: Force Discharge
            then:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {% set force_discharge_power =
                    states('number.force_discharge_power') | float %} {% set
                    charge_speed_for_7am =
                    states('sensor.foxess_charge_speed_for_7am') | float %} {%
                    if charge_speed_for_7am > 0 %}
                      {% set power = states('sensor.FoxESS_overnight_discharge_rate_kW') | float(4) | round(2) %}
                    {% else %}
                      {# We have reached the target SoC, and we are close in time to the end, so stay at this level #}
                      {% set power = (states('sensor.pv_power')| float) + 0.1 %}
                    {% endif %}     {% if force_discharge_power > power * 0.95
                    and force_discharge_power < power * 1.05 %}
                      {% set power = force_discharge_power %}
                    {% endif %}  {{ power }}
                target:
                  entity_id: number.force_discharge_power
          - choose:
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 97
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(0.5 - (states('sensor.pv_power')| float),
                        (0.5 / 2))  %}  {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 95
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(0.7 - (states('sensor.pv_power')| float),
                        (0.7 / 2))  %}  {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 94
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(1 - (states('sensor.pv_power')| float), (1 /
                        2))  %} {% if force_charge_power > power * 0.95 and
                        force_charge_power < power * 1.05 %}
                          {% set power = force_charge_power %}
                        {% endif %} {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 93
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(1.25 - (states('sensor.pv_power')| float),
                        (1.25 / 2))  %} {% if force_charge_power > power * 0.95
                        and force_charge_power < power * 1.05 %}
                          {% set power = force_charge_power %}
                        {% endif %} {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 92
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(1.5- (states('sensor.pv_power')| float),
                        (1.5 / 2))  %} {% if force_charge_power > power * 0.95
                        and force_charge_power < power * 1.05 %}
                          {% set power = force_charge_power %}
                        {% endif %} {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 91
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(1.75 - (states('sensor.pv_power')| float),
                        (1.75 / 2))  %} {% if force_charge_power > power * 0.95
                        and force_charge_power < power * 1.05 %}
                          {% set power = force_charge_power %}
                        {% endif %} {{ power }}
                    target:
                      entity_id: number.force_charge_power
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.battery_soc
                    above: 90
                sequence:
                  - action: number.set_value
                    metadata: {}
                    data:
                      value: >-
                        {% set force_charge_power =
                        states('number.force_charge_power') | float %} {% set
                        power = max(2 - (states('sensor.pv_power')| float), (2 /
                        2))  %} {% if force_charge_power > power * 0.95 and
                        force_charge_power < power * 1.05 %}
                          {% set power = force_charge_power %}
                        {% endif %} {{ power }}
                    target:
                      entity_id: number.force_charge_power
      - conditions:
          - condition: time
            after: "06:30:00"
          - condition: state
            entity_id: automation.foxess_calibrate_set_top_soc_reached
            state: "on"
        sequence:
          - if:
              - condition: state
                entity_id: select.work_mode
                state: Force Charge
            then:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {% set force_charge_power =
                    states('number.force_charge_power') | float %} {% set power
                    = states('sensor.foxess_charge_speed_for_7am') | float |
                    round(2) %}    {% if power < 0.1 %}
                      {# We have reached the target SoC, and we are close in time to the end, so stay at this level #}
                      {% set power = 0.1 %}
                    {% elif force_charge_power > power * 0.95 and
                    force_charge_power < power * 1.05 %}
                      {% set power = force_charge_power %}
                    {% endif %} {{ power }}    
                target:
                  entity_id: number.force_charge_power
            else:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {% set force_discharge_power =
                    states('number.force_discharge_power') | float %} {% set
                    charge_speed_for_7am =
                    states('sensor.foxess_charge_speed_for_7am') | float %}  {%
                    if charge_speed_for_7am > 0 %}
                      {% set power = states('sensor.FoxESS_overnight_discharge_rate_kW') | float(4) | round(2) %}
                    {% else %}
                      {# We have reached the target SoC, and we are close in time to the end, so stay at this level #}
                      {% set power = (states('sensor.pv_power')| float) + 0.1 %}
                    {% endif %}    {% if force_discharge_power > power * 0.95
                    and force_discharge_power < power * 1.05 %}
                      {% set power = force_discharge_power %}
                    {% endif %}                     {{ power }}
                target:
                  entity_id: number.force_discharge_power
      - conditions:
          - condition: time
            after: "00:02:00"
            before: "06:57:59"
        sequence:
          - if:
              - condition: state
                entity_id: select.work_mode
                state: Force Charge
            then:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {% set charge_speed_for_7am =
                    states('sensor.foxess_charge_speed_for_7am') | float %} {%
                    set overnight_charge_rate_kW =
                    states('sensor.FoxESS_overnight_charge_rate_kW') | float %}
                    {% set force_charge_power =
                    (states('number.force_charge_power') | float) %}   {% set
                    new_charge_power = max(overnight_charge_rate_kW,
                    charge_speed_for_7am)| round(2) %}   {% if (new_charge_power
                    <= (force_charge_power * 1.05)) and (new_charge_power >=
                    (force_charge_power * 0.95)) %}
                      {# If we are already close to the force charge power, don't change it #}
                      {% set new_charge_power = force_charge_power %}
                    {% endif %} {{ new_charge_power }}
                target:
                  entity_id: number.force_charge_power
            else:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {% set force_discharge_power =
                    states('number.force_discharge_power') | float %} {% set
                    power = states('sensor.FoxESS_overnight_discharge_rate_kW')
                    | float(4) | round(2) %} {% if force_discharge_power > power
                    * 0.95 and force_discharge_power < power * 1.05 %}
                      {% set power = force_discharge_power %}
                    {% endif %}                     {{ power }}
                target:
                  entity_id: number.force_discharge_power
mode: single


Code: Select all

alias: FoxESS_does_bottom_calibrate_need_to_run_today
description: >-
  Check whether bottom calibration needs to be run for the day.  This will
  happen if calibration has not happened for more than a certain number of days,
  or if  the normal bottom_soc is set to the extremes which will happen if the
  solar forecast is particularly low.  It is recommended that this be  done on a
  monthly schedule.  Set the trigger to run at the start of the cheap import
  period.
triggers:
  - trigger: time_pattern
    hours: "15"
    minutes: "55"
    seconds: "55"
  - trigger: time_pattern
    hours: "16"
    minutes: "55"
    seconds: "55"
  - trigger: state
    entity_id:
      - select.work_mode
    from: Feed-in First
    to: Force Discharge
  - trigger: state
    entity_id:
      - select.work_mode
    to: Force Discharge
    from: Self Use
conditions:
  - condition: state
    entity_id: input_boolean.foxess_calibrate_bottom_reached
    state: "on"
  - condition: time
    after: "15:00:00"
    before: "20:00:00"
  - condition: or
    conditions:
      - condition: template
        value_template: >-
          {{
          (states('input_datetime.foxess_calibrate_bottom_reached_date')|as_datetime).date()
          <=
          (now()-timedelta(days=(states('input_number.foxess_calibrate_days_between_bottom_calibration')
          | int))).date() }}
      - condition: numeric_state
        entity_id: input_number.foxess_daytime_discharge_bottom_soc
        below: 12
      - condition: template
        value_template: >-
          {{
          (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
          <= 35) }}
      - condition: template
        value_template: >-
          {{
          (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
          <= 40) and
          (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
          <=
          states('sensor.foxess_highest_vs_forecast_tomorrow_spread')|float(100))
          }}
      - condition: and
        conditions:
          - condition: or
            conditions:
              - condition: template
                value_template: >-
                  {{
                  (states('input_datetime.foxess_calibrate_top_reached_date')|as_datetime).date()
                  >= (now()-timedelta(days=1)).date() }}  
              - condition: numeric_state
                entity_id: input_number.foxess_daytime_discharge_bottom_soc
                below: 14
              - condition: template
                value_template: >-
                  {{
                  (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
                  <= 40) }}
              - condition: template
                value_template: >-
                  {{
                  (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
                  <= 50) and
                  (states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
                  <=
                  states('sensor.foxess_highest_vs_forecast_tomorrow_spread')|float(100))
                  }}
          - condition: template
            value_template: >-
              {{
              (states('input_datetime.foxess_calibrate_bottom_reached_date')|as_datetime).date()
              <=
              (now()-timedelta(days=(states('input_number.foxess_calibrate_days_between_bottom_calibration')
              | int - 6))).date() }}
  - condition: numeric_state
    entity_id: sensor.battery_soc
    above: sensor.min_soc_on_grid
actions:
  - action: input_boolean.turn_off
    metadata: {}
    data: {}
    target:
      entity_id: input_boolean.foxess_calibrate_bottom_reached
  - action: input_boolean.turn_on
    metadata: {}
    data: {}
    target:
      entity_id: input_boolean.foxess_calibrate_today
  - action: input_number.set_value
    metadata: {}
    data:
      value: 1
    target:
      entity_id: input_number.foxess_overnight_calibration_modifier
mode: single


Code: Select all

alias: FoxESS_does_top_calibrate_need_to_run_today
description: >-
  Check whether either top calibration needs to be run for the day.  This will
  happen if calibration has not happened for more than a certain number of days,
  or if  the normal top_soc is set to the max, which will happen if the solar 
  forecast is particularly low).   It is recommended  that these be done on a
  weekly schedule.  Set the trigger to run at the start of the cheap import
  period.
triggers:
  - trigger: time_pattern
    hours: "0"
    minutes: "0"
    seconds: "43"
conditions:
  - condition: or
    conditions:
      - condition: template
        value_template: >-
          {{ states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
          <= 35 }}
      - condition: template
        value_template: >-
          {{
          (states('input_datetime.foxess_calibrate_top_reached_date')|as_datetime).date()
          <=
          (now()-timedelta(days=(states('input_number.foxess_calibrate_days_between_top_calibration')
          | int))).date() }}
      - condition: numeric_state
        entity_id: input_number.foxess_overnight_charge_top_soc
        above: 95
actions:
  - if:
      - condition: or
        conditions:
          - condition: template
            value_template: >-
              {{
              states('sensor.foxess_highest_vs_forecast_today_spread')|float(100)
              <= 35 }}
          - condition: numeric_state
            entity_id: input_number.foxess_overnight_charge_top_soc
            above: 95
          - condition: template
            value_template: >-
              {{
              (states('input_datetime.foxess_calibrate_top_reached_date')|as_datetime).date()
              <=
              (now()-timedelta(days=(states('input_number.foxess_calibrate_days_between_top_calibration')
              | int))).date() }}
    then:
      - action: input_boolean.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: input_boolean.foxess_calibrate_top_reached
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1.2
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
        enabled: true
    else:
      - action: input_boolean.turn_on
        metadata: {}
        data: {}
        target:
          entity_id: input_boolean.foxess_calibrate_top_reached
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
        enabled: true
  - if:
      - condition: or
        conditions:
          - condition: state
            entity_id: input_boolean.foxess_calibrate_top_reached
            state: "off"
          - condition: state
            entity_id: input_boolean.foxess_calibrate_bottom_reached
            state: "off"
    then:
      - action: input_boolean.turn_on
        metadata: {}
        data: {}
        target:
          entity_id: input_boolean.foxess_calibrate_today
    else:
      - action: input_boolean.turn_off
        metadata: {}
        data: {}
        target:
          entity_id: input_boolean.foxess_calibrate_today
      - action: input_number.set_value
        metadata: {}
        data:
          value: 1
        target:
          entity_id: input_number.foxess_overnight_calibration_modifier
        enabled: true
mode: single


Code: Select all


alias: FoxESS Force charge overnight
description: ""
triggers:
  - trigger: state
    entity_id:
      - input_boolean.eon_next_drive_cheap_period
    to: "on"
  - trigger: state
    entity_id:
      - sensor.battery_soc
  - trigger: time
    at: "00:00:05"
  - trigger: time
    at: "00:02:05"
  - trigger: time
    at: "00:20:05"
  - trigger: time
    at: "00:40:05"
  - trigger: time
    at: "01:00:05"
  - trigger: time
    at: "01:20:05"
  - trigger: time
    at: "01:40:05"
  - trigger: time
    at: "02:00:05"
  - trigger: time
    at: "02:20:05"
  - trigger: time
    at: "02:40:05"
  - trigger: time
    at: "03:00:05"
  - trigger: time
    at: "03:10:05"
  - trigger: time
    at: "03:20:05"
  - trigger: time
    at: "03:30:05"
  - trigger: time
    at: "03:40:05"
  - trigger: time
    at: "03:50:05"
  - trigger: time
    at: "04:00:05"
  - trigger: time
    at: "04:06:05"
  - trigger: time
    at: "04:12:05"
  - trigger: time
    at: "04:18:05"
  - trigger: time
    at: "04:24:05"
  - trigger: time
    at: "04:30:05"
  - trigger: time
    at: "04:36:05"
  - trigger: time
    at: "04:42:05"
  - trigger: time
    at: "04:48:05"
  - trigger: time
    at: "04:54:05"
  - trigger: time
    at: "05:00:05"
  - trigger: time
    at: "05:06:05"
  - trigger: time
    at: "05:12:05"
  - trigger: time
    at: "05:18:05"
  - trigger: time
    at: "05:24:05"
  - trigger: time
    at: "05:30:05"
  - trigger: time
    at: "05:36:05"
  - trigger: time
    at: "05:42:05"
  - trigger: time
    at: "05:48:05"
  - trigger: time
    at: "05:54:05"
  - trigger: time
    at: "06:00:05"
  - trigger: time
    at: "06:03:05"
  - trigger: time
    at: "06:06:05"
  - trigger: time
    at: "06:09:05"
  - trigger: time
    at: "06:12:05"
  - trigger: time
    at: "06:15:05"
  - trigger: time
    at: "06:18:05"
  - trigger: time
    at: "06:21:05"
  - trigger: time
    at: "06:24:05"
  - trigger: time
    at: "06:27:05"
  - trigger: time
    at: "06:30:05"
  - trigger: time
    at: "06:33:05"
  - trigger: time
    at: "06:36:05"
  - trigger: time
    at: "06:39:05"
  - trigger: time
    at: "06:42:05"
  - trigger: time
    at: "06:45:05"
  - trigger: time
    at: "06:48:05"
  - trigger: time
    at: "06:51:05"
  - trigger: time
    at: "06:54:05"
  - trigger: time
    at: "06:57:05"
  - trigger: time
    at: "06:58:05"
conditions:
  - condition: state
    entity_id: input_boolean.eon_next_drive_cheap_period
    state: "on"
  - condition: time
    after: "00:00:00"
    before: "06:58:00"
  - condition: or
    conditions:
      - condition: numeric_state
        entity_id: sensor.battery_soc
        below: 55
      - condition: and
        conditions:
          - condition: template
            value_template: >-
              {% if states('input_boolean.foxess_calibrate_top_reached') | bool
              %}
                {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 55) %} 
                {% set top_soc = states('input_number.foxess_overnight_charge_top_soc') | float %} 
              {% else %}
                {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 20) %} 
                {% set top_soc = states('input_number.foxess_calibrate_top_soc') | float %} 
              {% endif %}  {{ ((states('sensor.foxess_charge_speed_for_7am') |
              float) >= (states('number.force_charge_power') | float * perc_time
              * 0.9)) and ((states('sensor.battery_soc') | float) < (top_soc *
              perc_time)) }}
          - condition: numeric_state
            entity_id: sensor.foxess_charge_speed_for_7am
            above: 0
          - condition: time
            before: "06:00:00"
      - condition: and
        conditions:
          - condition: template
            value_template: >-
              {{ (states('sensor.foxess_charge_speed_for_7am') | float) >=
              (states('number.force_charge_power') | float * 0.95) }}
          - condition: numeric_state
            entity_id: sensor.foxess_charge_speed_for_7am
            above: 0
  - condition: or
    conditions:
      - condition: and
        conditions:
          - condition: state
            entity_id: select.work_mode
            state: Force Discharge
          - condition: template
            value_template: >-
              {{ (states('sensor.foxess_charge_speed_for_7am') | float) >=
              (states('number.force_charge_power') | float * 0.93) }}
          - condition: numeric_state
            entity_id: sensor.foxess_charge_speed_for_7am
            above: 0
      - condition: state
        entity_id: select.work_mode
        state: Force Discharge
        for:
          hours: 0
          minutes: 25
          seconds: 0
      - condition: and
        conditions:
          - condition: state
            entity_id: select.work_mode
            state: Force Discharge
            for:
              hours: 0
              minutes: 5
              seconds: 0
          - condition: template
            value_template: >-
              {{ (states('sensor.load_power') | float) >=
              (states('number.force_discharge_power') | float * 0.5) }}
      - condition: state
        entity_id: select.work_mode
        state: Self Use
      - condition: state
        entity_id: select.work_mode
        state: Feed-in First
      - condition: state
        entity_id: select.work_mode
        state: Back-up
      - condition: state
        entity_id: select.work_mode
        state: unavailable
      - condition: state
        entity_id: select.work_mode
        state: unknown
      - condition: and
        conditions:
          - condition: state
            entity_id: select.work_mode
            state: Force Discharge
          - condition: numeric_state
            entity_id: sensor.battery_soc
            below: 25
actions:
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: time
                after: "00:00:01"
                before: "00:01:59"
              - condition: time
                after: "06:58:00"
                before: "07:00:00"
              - condition: numeric_state
                entity_id: sensor.foxess_charge_speed_for_7am
                below: 0.1
        sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: "0.4"
            target:
              entity_id: number.force_charge_power
          - action: select.select_option
            metadata: {}
            data:
              option: Force Charge
            target:
              entity_id: select.work_mode
          - if:
              - condition: numeric_state
                entity_id: sensor.foxess_charge_speed_for_7am
                below: 0.1
            then:
              - action: input_text.set_value
                metadata: {}
                data:
                  value: Reached target SoC - minimal charge
                target:
                  entity_id: input_text.foxess_schedule_mode
            else:
              - if:
                  - condition: time
                    after: "06:58:00"
                    before: "07:00:00"
                then:
                  - action: input_text.set_value
                    metadata: {}
                    data:
                      value: Transition to day - minimal charge
                    target:
                      entity_id: input_text.foxess_schedule_mode
                else:
                  - action: input_text.set_value
                    metadata: {}
                    data:
                      value: Transition to overnight - minimal charge
                    target:
                      entity_id: input_text.foxess_schedule_mode
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: time
                after: "06:30:00"
                before: "06:57:59"
              - condition: template
                value_template: >-
                  {{ (states('sensor.foxess_charge_speed_for_7am') | float) >=
                  (states('sensor.foxess_overnight_charge_rate_kw') | float |
                  round(2)) }}
        sequence:
          - if:
              - condition: numeric_state
                entity_id: sensor.battery_soc
                below: 90
            then:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {{ states('sensor.foxess_charge_speed_for_7am') | float |
                    round(2) }}
                target:
                  entity_id: number.force_charge_power
          - action: select.select_option
            metadata: {}
            data:
              option: Force Charge
            target:
              entity_id: select.work_mode
          - action: input_text.set_value
            metadata: {}
            data:
              value: Final overnight charge
            target:
              entity_id: input_text.foxess_schedule_mode
  - choose:
      - conditions:
          - condition: time
            after: "00:02:00"
            before: "06:29:59"
        sequence:
          - if:
              - condition: numeric_state
                entity_id: sensor.battery_soc
                below: 90
            then:
              - action: number.set_value
                metadata: {}
                data:
                  value: >-
                    {{ states('sensor.foxess_overnight_charge_rate_kw') | float
                    | round(2) }}
                target:
                  entity_id: number.force_charge_power
          - action: select.select_option
            metadata: {}
            data:
              option: Force Charge
            target:
              entity_id: select.work_mode
          - action: input_text.set_value
            metadata: {}
            data:
              value: Overnight charge
            target:
              entity_id: input_text.foxess_schedule_mode
  - action: select.select_option
    metadata: {}
    data:
      option: Force Charge
    target:
      entity_id: select.work_mode
  - action: input_text.set_value
    metadata: {}
    data:
      value: Overnight charge (default)
    target:
      entity_id: input_text.foxess_schedule_mode
mode: single



Code: Select all


alias: FoxESS Force Discharge Overnight
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.battery_soc
  - trigger: state
    entity_id:
      - input_boolean.foxess_calibrate_top_reached
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 5
  - trigger: time
    at: "01:40:00"
  - trigger: time
    at: "02:05:00"
  - trigger: time
    at: "02:30:00"
  - trigger: time
    at: "02:55:00"
  - trigger: time
    at: "03:20:00"
  - trigger: time
    at: "03:45:00"
  - trigger: time
    at: "04:10:00"
  - trigger: time
    at: "04:35:00"
  - trigger: time
    at: "05:00:00"
  - trigger: time
    at: "05:20:00"
  - trigger: time
    at: "05:30:00"
  - trigger: time
    at: "05:40:00"
  - trigger: time
    at: "05:50:00"
  - trigger: time
    at: "06:15:00"
  - trigger: time
    at: "06:35:00"
  - trigger: time
    at: "06:59:00"
conditions:
  - condition: or
    conditions:
      - condition: and
        conditions:
          - condition: time
            after: "00:02:00"
            before: "06:30:00"
          - condition: template
            value_template: >-
              {% if states('input_boolean.foxess_calibrate_top_reached') | bool
              %}
                {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 55) %} 
                {% set top_soc = states('input_number.foxess_overnight_charge_top_soc') | float %} 
              {% else %}
                {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 20) %} 
                {% set top_soc = states('input_number.foxess_calibrate_top_soc') | float %} 
              {% endif %}  {{ (states('sensor.foxess_battery_soc_exact') |
              float) > (40 + ((top_soc-40) * perc_time * 0.6))}}
          - condition: or
            conditions:
              - condition: and
                conditions:
                  - condition: template
                    value_template: >-
                      {% if states('input_boolean.foxess_calibrate_top_reached')
                      | bool %}
                        {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 55) %}  
                        {% set top_soc = states('input_number.foxess_overnight_charge_top_soc') | float %} 
                      {% else %}
                        {% set perc_time = (((now().strftime("%H") | int) * 60 + (now().strftime("%M") | int) )) / (6 * 60 + 20) %}  
                        {% set top_soc = states('input_number.foxess_calibrate_top_soc') | float %} 
                      {% endif %}   {{
                      (((states('sensor.foxess_charge_speed_for_7am') | float)
                      <= (states('number.force_charge_power') | float *
                      perc_time * 0.9)) or ((states('sensor.battery_soc') |
                      float) > (top_soc * perc_time))) and
                      ((states('sensor.foxess_charge_speed_for_7am') | float) <
                      (states('number.force_charge_power') | float * 0.9)) }}
                  - condition: numeric_state
                    entity_id: sensor.foxess_charge_speed_for_7am
                    above: 0
                  - condition: time
                    before: "06:30:00"
              - condition: and
                conditions:
                  - condition: template
                    value_template: >-
                      {% if states('input_boolean.foxess_calibrate_top_reached')
                      | bool %}
                        {% set top_soc = states('input_number.foxess_overnight_charge_top_soc') | float %} 
                      {% else %}
                        {% set top_soc = states('input_number.foxess_calibrate_top_soc') | float %} 
                      {% endif %}  {{ (states('sensor.battery_soc') | float) >=
                      top_soc }}                    
          - condition: or
            conditions:
              - condition: time
                after: "06:59:00"
              - condition: and
                conditions:
                  - condition: time
                    before: "05:45:00"
                  - condition: or
                    conditions:
                      - condition: state
                        entity_id: select.work_mode
                        state: Force Charge
                        for:
                          hours: 0
                          minutes: 35
                          seconds: 0
                      - condition: numeric_state
                        entity_id: sensor.battery_soc
                        above: 99
              - condition: and
                conditions:
                  - condition: time
                    after: "05:45:00"
                  - condition: or
                    conditions:
                      - condition: state
                        entity_id: select.work_mode
                        state: Force Charge
                        for:
                          hours: 0
                          minutes: 20
                          seconds: 0
                      - condition: numeric_state
                        entity_id: sensor.battery_soc
                        above: 99
              - condition: and
                conditions:
                  - condition: state
                    entity_id: select.work_mode
                    state: Force Charge
                  - condition: template
                    value_template: >-
                      {% if states('input_boolean.foxess_calibrate_top_reached')
                      | bool %}
                        {% set top_soc = states('input_number.foxess_overnight_charge_top_soc') | float %} 
                      {% else %}
                        {% set top_soc = states('input_number.foxess_calibrate_top_soc') | float %} 
                      {% endif %}                       {{
                      (states('sensor.battery_soc') | float) >= top_soc }}
                  - condition: time
                    before: "06:30:00"
      - condition: and
        conditions:
          - condition: time
            after: "06:57:59"
            before: "07:00:00"
  - condition: or
    conditions:
      - condition: and
        conditions:
          - condition: time
            after: "06:00:00"
          - condition: template
            value_template: >-
              {{ ((states('sensor.foxess_charge_speed_for_7am') | float) <
              (states('number.force_charge_power') | float * 0.75)) and
              (states('sensor.foxess_overnight_discharge_rate_kw')|float >
              (states('sensor.load_power')|float * 2.0)) }}    
      - condition: and
        conditions:
          - condition: time
            after: "06:30:00"
          - condition: template
            value_template: >-
              {{ ((states('sensor.foxess_charge_speed_for_7am') | float) <
              (states('number.force_charge_power') | float * 0.65))  and
              (states('sensor.foxess_overnight_discharge_rate_kw')|float >
              (states('sensor.load_power')|float * 2.0)) }}    
      - condition: and
        conditions:
          - condition: time
            after: "05:30:00"
          - condition: template
            value_template: >-
              {{ ((states('sensor.foxess_charge_speed_for_7am') | float) <
              (states('number.force_charge_power') | float * 0.80))  and
              (states('sensor.foxess_overnight_discharge_rate_kw')|float >
              (states('sensor.load_power')|float * 2.0)) }}    
      - condition: and
        conditions:
          - condition: time
            before: "05:30:00"
          - condition: template
            value_template: >-
              {{ ((states('sensor.foxess_charge_speed_for_7am') | float) <
              (states('number.force_charge_power') | float * 0.85)) and
              (states('sensor.foxess_overnight_discharge_rate_kw')|float >
              (states('sensor.load_power')|float * 2.0)) }}    
      - condition: time
        after: "06:59:00"
actions:
  - action: select.select_option
    metadata: {}
    data:
      option: Force Discharge
    target:
      entity_id: select.work_mode
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: time
                after: "06:58:00"
              - condition: template
                value_template: >-
                  {% set target_soc =
                  states('input_number.foxess_calibrate_top_soc') | float %}

                  {% if states('input_boolean.foxess_calibrate_top_reached') |
                  bool %}
                    {% set target_soc = states('input_number.foxess_overnight_charge_top_soc') | float %}
                  {% endif %}

                  {{states('sensor.battery_soc') | float >= target_soc}}
        sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: "{{(states('sensor.pv_power')| float) + 0.4}}"
            target:
              entity_id: number.force_discharge_power
          - if:
              - condition: template
                value_template: >-
                  {% set target_soc =
                  states('input_number.foxess_calibrate_top_soc') | float %}

                  {% if states('input_boolean.foxess_calibrate_top_reached') |
                  bool %}
                    {% set target_soc = states('input_number.foxess_overnight_charge_top_soc') | float %}
                  {% endif %}

                  {{states('sensor.battery_soc') | float >= target_soc}}
            then:
              - action: input_text.set_value
                metadata: {}
                data:
                  value: Target SoC reached - minimal export
                target:
                  entity_id: input_text.foxess_schedule_mode
            else:
              - action: input_text.set_value
                metadata: {}
                data:
                  value: Transition to day - minimal export
                target:
                  entity_id: input_text.foxess_schedule_mode
  - choose:
      - conditions:
          - condition: time
            before: "06:58:00"
        sequence:
          - action: number.set_value
            metadata: {}
            data:
              value: >-
                {{(states('sensor.foxess_overnight_discharge_rate_kw') | float |
                round(2)) }}
            target:
              entity_id: number.force_discharge_power
          - action: input_text.set_value
            metadata: {}
            data:
              value: Overnight arbitrage export
            target:
              entity_id: input_text.foxess_schedule_mode
mode: single


/code]
Re: EP11 (LiFePo4) best SoC range for longevity?
Thanks a lot. Even with adjusting, it gets me off to a great start.
Post Reply