alias: Initialize Battery Depletion Time
description: ""
trigger:
- platform: state
entity_id:
- input_boolean.house_power_status
to: "off"
condition: []
action:
- service: input_datetime.set_datetime
data:
datetime: "'1970-01-01 00:00:00'"
target:
entity_id: input_datetime.estimated_battery_depletion_time
mode: single
alias: Set Time Battery Depleted
description: ""
trigger:
- platform: time_pattern
minutes: /5
condition:
- condition: state
entity_id: input_boolean.house_power_status
state: "off"
action:
- service: input_datetime.set_datetime
data:
timestamp: |
{% if states('sensor.a70_battery_level') | float < 0.0 %}
{{ (((states('sensor.a70_battery_level') | float(0) - states('input_number.battery_setpoint') | float(0)) / states('sensor.a70batterycharge') | float(0) | abs) * 60) + as_timestamp(now())}}
{% else %}
{{ as_timestamp(now()) + 86400 }}
{% endif %}
target:
entity_id: input_datetime.estimated_battery_depletion_time
mode: single
![a70turev|525x500](upload://q2dM4m9693hlKbCDaFJ1xTk1N94.png)
![a70turev2|499x500](upload://lEHfyNq3GACXCCc63Y4R0sLnzno.png)
Right, I cannot believe that I looked forward to loadshedding tonight. So, I got everything set up and basically it kept on keeping to the same time, if not earlier.
So, I looked deeper into the formula above and simply swapped the āinput_number.battery_setpointā and āsensor.battery_state_of_chargeā around and it seems I am getting a fair prediction.
I probably can swap out the setpoint input numeric just with 100 that should be fine as the setpoint is 100, being the batteryās full charge. Nevertheless, currently, as I type this, my SOC is 68% to deplete at 10:39pm ā¦ it is now 9:37pmā¦ This seems pretty much what I expected. Iām going to monitor this and see how it goes.
Actually talking about the setpoint, I changed mine to 70 because at 30% SOC, my inverter shuts the power off to the house so that it can keep running the inverter until grid power is restored. Changing that, has definitely made the predicted time more realistic.
Can you share the place you changed with the code? I want to apply it immediately
Yeah, I think thatās itā¦ Iāll test it, of course. I set the trigger time to 10 sec. I set the frequency of sending battery level data from the phone to fast. Now realistic values started to occurā¦ The time is approximately 00:41 and the current battery level is 46%ā¦ The final version of my code:
alias: Set Time Battery Depleted
description: ""
trigger:
- platform: time_pattern
seconds: /10
condition:
- condition: state
entity_id: input_boolean.house_power_status
state: "off"
action:
- service: input_datetime.set_datetime
data:
timestamp: |
{% if states('sensor.a70batterycharge') | float < 0.0 %}
{{ (((states('sensor.a70_battery_level') | float(0) - states('input_number.battery_setpoint') | float(0)) / states('sensor.a70batterycharge') | float(0) | abs) * 60) + as_timestamp(now())}}
{% else %}
{{ as_timestamp(now()) + 86400 }}
{% endif %}
target:
entity_id: input_datetime.estimated_battery_depletion_time
mode: single
So you are saying the formula is this:
{{ (((states('input_number.setpoint') | float(0) - states('sensor.battery_soc') | float(0)) / states('sensor.battery_discharge_derivative') | float(0) | abs) * 60) + as_timestamp(now())}}
I donāt see how that could not give a negative value and then subtract the time from now instead of add to it.
is the input_number_setpoint value higher than the sensor.battery_soc value?
@finity I scrolled up to one of your posts above where you mentioned that the setpoint is actually a battery empty setpoint aka when one would consider the battery as depleted. In my case, my inverter shuts the power off at 30%, so in hindsight, the set point should be 30 and thus, the values should not be swapped around. We have loadshedding tonight at 6pm, so will put the values back, set the setpoint correctly and monitor.
Yeah, thatās what I was referring to.
the entity_id was poorly chosen (battery_setpoint) and thatās why I first said
Hopefully now that itās better understood then it should get you closer to working it out.
Hi @ipodmusicman, Iām quite new to HA and you seem to be a advanced user. Where did you learn all the scripting tricks - did you just read through endless forums or had some good book or other resource?
At the moment Iām trying to set a trigger for my batteryās SOC. According to me [states.]sensor.battery_state_of_charge
should work but it doesnāt - thatās the level of knowledge Iām at.
@ipodmusicman - Thank you for creating this post - This is exactly what Iām looking for.
This post has a lot of fragmented pieces of code. Would you mind sharing your final templates/helpers and automations?
Hi there, noooo, lots of Googling and searching on this forum. Although I am a software engineer by profession, Jinja has always been a bit of a sticking point, so Iāve managed to find all the help from many awesome community members on this forum.
Hi folks,
@jacauc FYI good suggestion.
Here is my complete solution and it works brilliantly! I have been keeping an eye on this during many loadshedding events and Iām very happy with the result.
Firstly, I defined an input number helper which acts as the battery setpoint. Its entity ID is input_number.battery_setpoint.
The maximum value is set to 10 with the step size set to 0,1
As contradictory to the posts above, I changed my inverter to shut the power off when the battery reaches 10% so this all measures based on the fact that the battery will deplete at 10%.
I defined an input date/time helper which acts as the estimated battery depletion time. Its entity ID is input_datetime.estimated_battery_depletion_time
I defined a derivative sensor helper which acts as the battery state of charge derivative. Its entity ID is sensor.battery_state_of_charge_derivative.
The derivative options are:
- Precision: 3
- Time window: 00:05:00 (5 minutes)
- Metric prefix: none
- Time unit: Minutes
I also have a binary sensor called binary_sensor.house_power_status. This specifies whether the house is on grid power or not.
I defined the following template sensors:
template:
- sensor:
- name: "Estimated Battery Depletion Time"
state: "{{ as_timestamp(states('input_datetime.estimated_battery_depletion_time')) | timestamp_custom('%-I:%M %p')}}"
icon: mdi:clock
- name: "Estimated Battery Depletion Time Countdown"
state: "{{ (as_timestamp(states('input_datetime.estimated_battery_depletion_time')) - as_timestamp(now())) | timestamp_custom('%H hr %M min', false)}}"
icon: mdi:timer-sand
I am not actively using the āEstimated Battery Depletion Time Countdownā as above though, so you can omit it.
These are the automations that are in play:
- alias: Initialize Battery Depletion Time
trigger:
- platform: state
entity_id: binary_sensor.house_power_status
to: 'off'
action:
- service: input_datetime.set_datetime
entity_id: input_datetime.estimated_battery_depletion_time
data:
datetime: '1970-01-01 00:00:00'
- alias: Set Time Battery Depleted
trigger:
- platform: time_pattern
minutes: "/5"
condition:
- condition: state
entity_id: binary_sensor.house_power_status
state: 'off'
action:
- service: input_datetime.set_datetime
entity_id: input_datetime.estimated_battery_depletion_time
data:
timestamp: >
{% if states('sensor.battery_state_of_charge_derivative') | float < 0.0 %}
{{ (((states('sensor.battery_state_of_charge') | float(0) - states('input_number.battery_setpoint') | float(0)) / states('sensor.battery_state_of_charge_derivative') | float(0) | abs) * 60) + as_timestamp(now())}}
{% else %}
{{ as_timestamp(now()) + 86400 }}
{% endif %}
On the UI side, I have a mushroom template card as below that shows me how many days, hours, minutes until the next loadshedding event is as well as what time the next loadshedding event is, but once power has gone off, it will show me the amount of time until the battery is depleted as well as the current SOC. The lightning bolt icon changes colour based on the status as below. This will also show me that if the power goes off outside of loadshedding, then it will show as a power failure. We have prepaid electricity so this is generally shown when the power has run out because I had forgotten to load the meter with more electricity.
type: custom:mushroom-template-card
primary: |-
{% if is_state('sensor.loadshedding_local_status', '0') %}
{% if is_state('binary_sensor.house_power_status', 'off') %}
Power failure
{% else %}
Not currently loadshedding
{% endif %}
{% else %}
{% if is_state('calendar.loadshedding_local_events', 'on') and
is_state('binary_sensor.house_power_status', 'off') %}
Loadshedding in progress .. back on in {{ (((as_timestamp(states.calendar.loadshedding_local_events.attributes.end_time)) - as_timestamp(now()) ) % 86400 // 3600) | round(0) | int }} hr {{ (((as_timestamp(states.calendar.loadshedding_local_events.attributes.end_time)) - as_timestamp(now()) ) % 86400 // 60) | round(0) | int % 60 }} min
{% elif is_state('calendar.loadshedding_local_events', 'off') and
is_state('binary_sensor.house_power_status', 'off') %}
Power failure
{% elif is_state('calendar.loadshedding_local_events', 'on') and
is_state('binary_sensor.house_power_status', 'on') %}
{% if ((((as_timestamp(states.calendar.loadshedding_local_events.attributes.end_time)) - as_timestamp(now()) ) % 86400 // 60) | round(0) | int % 60) > 60 %}
Loadshedding to kick in shortly ...
{% else %}
Power restored
{% endif %}
{% else %}
{% if (as_timestamp(states.calendar.loadshedding_local_events.attributes.start_time)) - as_timestamp(now()) < 0 %}
No upcoming loadshedding schedule available
{% else %}
Loadshedding in {{ state_attr('sensor.loadshedding_local_status', 'Area') }} in
{{ (((as_timestamp(states.calendar.loadshedding_local_events.attributes.start_time)) - as_timestamp(now())) // 86400) | round(0) | int }} d {{ (((as_timestamp(states.calendar.loadshedding_local_events.attributes.start_time)) - as_timestamp(now())) % 86400 // 3600) | round(0) | int }} hr {{ (((as_timestamp(states.calendar.loadshedding_local_events.attributes.start_time)) - as_timestamp(now())) % 3600 // 60) | round(0) | int }} min
{% endif %}
{% endif %}
{% endif %}
secondary: |
{% if is_state('binary_sensor.house_power_status', 'off') %}
Battery at {{ states('sensor.battery_state_of_charge') }} %.
Battery to run out at {{ states('sensor.estimated_battery_depletion_time') }}
{% elif not is_state('sensor.loadshedding_local_status', '0') %}
{{ state_attr('calendar.loadshedding_local_events', 'start_time') }} to {{ as_timestamp(states.calendar.loadshedding_local_events.attributes.end_time) | timestamp_custom("%H:%M:%S") }}
{% endif %}
icon: mdi:lightning-bolt
icon_color: |-
{% if is_state('sensor.loadshedding_local_status', '0') %}
{% if is_state('binary_sensor.house_power_status', 'off') %}
red
{% else %}
green
{% endif %}
{% else %}
{% if is_state('calendar.loadshedding_local_events', 'on') and
is_state('binary_sensor.house_power_status', 'off') %}
yellow
{% elif is_state('calendar.loadshedding_local_events', 'off') and
is_state('binary_sensor.house_power_status', 'off') %}
red
{% else %}
{% if (as_timestamp(states.calendar.loadshedding_local_events.attributes.start_time)) - as_timestamp(now()) < 0 %}
yellow
{% else %}
yellow
{% endif %}
{% endif %}
{% endif %}
fill_container: false
multiline_secondary: false