So I’ve managed to get this working the way I’d like - I have no idea if it’s the best way to do it but it definitely works for me…
The setup consists of:
- An
input_datetime
(input_datetime.softener_salt
)
- A template sensor (
sensor.softener_salt_last_replaced
)
- A file notification (
notify.water_softener
)
- A file sensor (
sensor.water_softener_average
)
- A couple of automations (
automation.action_water_softener_salt_replacement
& automation.notification_water_softener_salt
)
First, I created the input_datetime
and set it up to only record the date:
name: Softener Salt
has_date: true
has_time: false
icon: mdi:cube-outline
I then manually set that date to the last time I replaced the salt (only manually for the first time, afterwards it’ll be sorted with an automation).
After that I then created the template sensor that calculates the number of days that have passed between today and the timestamp of the input_datetime.softener_salt
(I’m convinced there must be a way to calculate based on dates rather than timestamps but I’ve not found it yet!
platform: template
sensors:
softener_salt_last_replaced:
value_template: '{{ ((as_timestamp(now())-(states.input_datetime.softener_salt.attributes.timestamp)) | int /60/1440) | round(0) }}'
unit_of_measurement: 'Days'
entity_id: input_datetime.softener_salt, sensor.date
friendly_name: 'Softener Salt'
I then needed a way to store the state of this sensor each time I refill the softener salt. For this I used the File integration where you’re able to log to a file when calling a notify service:
name: water_softener
platform: file
filename: water_softener.log
timestamp: true
Now I wanted a way to average the contents of the water_softener.log
to allow for an automation to be set up when sensor.softener_salt_last_replaced
went over the average number of days. For this, I couldn’t find anything native to Home Assistant, so instead I created my own Python script:
# Define the empty list to be added to later on
days = []
# Define a function to calculate the average of a list
def Average(lst):
return sum(lst) / len(lst)
# Open the water softener log
with open('/home/zander/homeassistant/water_softener.log') as file:
# Read the lines in the file, ensuring to skip the first two lines as they aren't needed
output = file.readlines()[2:]
# Remove '/n' from each item in the list
output = [item.rstrip() for item in output]
# Start a For Loop for every item in the output list
for items in output:
# Split the items at each blank space (needed as the file has timestamp then the number)
items_split = items.split(' ')
# Add the second item from what we've just split to the 'days' list we defined at the start
days.append(items_split[1])
# As the original file had the numbers (integers) stored as text (strings) we need to convert them to integers to be able to carry out calculations
days = list(map(int, days))
# Calculate the average number of days utilising the function we defined earlier
average_days = Average(days)
average_days = round(average_days)
# Close the file that we opened at the start
file.close()
# Open the file where we store averages
file = open("/home/zander/homeassistant/water_softener_average.txt", "a")
# Write a new line with the newly calculated average
file.write('\n' + str(average_days))
# Close the file
file.close()
This script outputs the average to a file called water_softener_average.txt
so I then needed to have this file as a sensor in Home Assistant. So I again utilised the File integration to allow me to create a sensor out of the contents of this file:
platform: file
file_path: /config/water_softener_average.txt
name: Water Softener Average
unit_of_measurement: 'Days'
Now I had everything I needed in order to create my automations. The first automation is what I will execute each time I refill the water softener salt:
alias: Action - Water Softener Salt Replacement
description: ''
trigger: []
condition: []
action:
- data:
message: '{{states(''sensor.softener_salt_last_replaced'')}}
'
service: notify.water_softener
- data: {}
service: python_script.softener_average_calculation
- data_template:
date: '{{ as_timestamp(now())|timestamp_custom(''%Y-%m-%d'') }}'
entity_id: input_datetime.softener_salt
service: input_datetime.set_datetime
mode: single
In its current state there are no triggers as I am utilising a button in lovelace to execute the automation until I can make / get my hands on a simple button device. The actions are pretty self explanatory:
- Log the current state (number of days) of
sensor.softener_salt_last_replaced
to file by calling notify.water_softener
.
- Execute my python script to calculate the new average now that there has been another addition to the
water_softener.log
.
- Reset
input_datetime.softener_salt
to today’s date to begin the count-up once again
Then my second automation simply notifies me if the value of sensor.softener_salt_last_replaced
goes above sensor.water_softener_average
:
alias: Notification - Water Softener Salt
description: ''
trigger:
- platform: template
value_template: '{{states(''sensor.softener_salt_last_replaced'') | int > states(''sensor.water_softener_average'')
| int}}'
condition: []
action:
- data:
message: Check the softener salt, it may need replacing soon
service: notify.zanders_devices
mode: single
And that’s it! Only time will tell whether it truly works but all of my tests thus far have proved it works as expected!
A massive thank you to @KTibow as they pointed me in the right direction for a lot of this, your help is massively appreciated!