I have a water softener CLACK WS1 with a salt container. It was set that it regenerates at night when X m3 have passed through it. It was not good for me, as it is loud process and my bedroom is right above the room where it is located. So I decided to run the regen process manually, but then I must check once a while screen of the CLACK head to know how much m3 are left there. As I could forget to do that, I had to add somehow this to HA and have a notification, every time X m3 are left and regen is needed. So I came up with this
Notifications in Lovelace
Water softener head:
Ingredients needed:
- aqara/mijia zigbee window sensors (and integration to HA. I use zigbee2mqtt (best thing ever)). Note: I guess RF window sensors also will do the trick, but I find them super unreliable.
- Smart outlet that has power measurement.
- Relay 15V (V probably depends on water softener also) ( I had only 5V relay, so I had to add also step down converter, from 15v - 5V)
In my CLACK WS1 motherboard, there is connector for relay with pins RL1;COM+. That is the place we will connect the window sensor. As you can program the head to send signal (in this case 15V to the pins) every time X liters has passed through the softener. In my case, I set the head to send the signal every 10 liters.
To do this, you have to press button together button NEXT and DOWN, till menu appears, then press NEXT till you see RELAY on screen, with UP/DOWN choose set softening and L symbol on screen, press NEXT, set desired amount of liters, press next and set time after how long the signal will be sent to relay.
Solider two wires on Window sensor, where the reed switch is, so when you connect together the wires the signal is sent. Add two wires to from water softener to relay (CHECK POLARITY AND CHECK THE VOLTAGE OF RELAY, AND MESURE BEFORE HOW MUCH V DOES THE WATER SOFTENER GIVE OUT), and from window sensor to normally open relay contacts.
^this was as I did, but probably it must be tweaked as individually needed.
Also the Input select as all other things below is needed to adjust individually.
In short it works like this.
I have set up that after every 4000 liters regen is needed, so it is set in input_number.water_softerner_meter_liters. every time pulse is detected from window sensor it subtracts 10 liters.
When Regeneration is started, my outlet gives me power reading that is largen than 2.8W, as the motor opens and closes the valves, in idle it is not more than 1W. From this I can tell, that cycle started. So in cycle automations it looks for the power above 2.8W and reads the input select selection, so it knows what cycle is running. On next >2.8W spike it knows the next cycle started. Also it sets the timer for every cycle when it starts.
It probably has a lot to improve, but for me it works quite good at the moment, and hey, “it’s not stupid if it works”
Be glad to hear what to improve, and maybe this would be useful for someone.
#-----------
#INPUT SELECT
#-----------
water_softener_status:
name: Water softener status
options:
- Backwash 1st
- Brine
- Backwash
- Rinse
- Fill
- Idle
initial: Idle
#-----------
#INPUT NUMBER
#-----------
water_softerner_meter_liters:
name: Water softener l left
min: 0
max: 999999
step: 10
unit_of_measurement: l
mode: box
#-----------
#TIMERS
#-----------
timer_ws_backwash1:
name: Backwash 1st
duration: '0:06:10'
timer_ws_brine:
name: Brine
duration: '0:70:04'
timer_ws_backwash:
name: Backwash
duration: '0:03:03'
timer_ws_rinse:
name: Rinse
duration: '0:04:10'
timer_ws_fill:
name: Fill
duration: '0:13:46'
timer_ws_total:
name: Total
duration: '1:37:40'
#-----------
#SENSORS
#-----------
- platform: template
sensors:
water_softener_m3_left:
friendly_name: Water softener m3 left
unit_of_measurement: 'm3'
value_template: >
{{ ((4000 - (states.input_number.water_softerner_meter_liters.state | int))*0.001) | round(2) }}
water_softener_l_left:
friendly_name: Water softener l left
unit_of_measurement: 'l'
value_template: >
{{ 4000 - (states.input_number.water_softerner_meter_liters.state | int) }}
water_softener_regen:
friendly_name: "Water filter regen needed"
value_template: >
{% set val = (states.sensor.water_softener_l_left.state | int) %}
{% if val > 1000 %}
False
{% elif val < 1000 %}
True
{% else %}
Error
{% endif %}
icon_template: >
{% set val = (states.sensor.water_softener_l_left.state | int) %}
{% if val > 1000 %}
mdi:beaker
{% elif val < 1000 %}
mdi:beaker-alert-outline
{% else %}
mdi:alert-octagram-outline
{% endif %}
#read power readings from outlet
- platform: mqtt
name: Water softener Power
state_topic: "tele/son-wsoftener/SENSOR"
value_template: '{{ value_json["ENERGY"]["Power"] }}'
unit_of_measurement: "W"
qos: 1
#Read last triggered state of mqtt
- platform: mqtt
state_topic: "home/lasttrigger/water_softener"
name: "water softener last triggered"
#-----------
#SWITCHES
#-----------
- platform: mqtt
name: "Water softener outlet"
state_topic: "stat/son-wsoftener/POWER"
command_topic: "cmnd/son-wsoftener/POWER"
qos: 1
payload_on: "ON"
payload_off: "OFF"
retain: false
#-----------
#AUTOMATIONS
#-----------
#pulse automation for aqara sensor
- alias: "Water softener - Pulse Received"
initial_state: true
trigger:
- platform: state
entity_id: binary_sensor.water_softener_pulse_contact
condition:
- condition: state
entity_id: binary_sensor.water_softener_pulse_contact
state: 'off'
action:
- service: input_number.set_value
data_template:
entity_id: input_number.water_softerner_meter_liters
value: "{{ (states.input_number.water_softerner_meter_liters.state | int ) + 10 }}"
#automations for water regen 5 cycles
#Backwash first
- alias: "Set water softener start Backwash 1st"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Idle
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Backwash 1st
- service: timer.start
entity_id: timer.timer_ws_backwash1
- service: timer.start
entity_id: timer.timer_ws_total
- service: input_number.set_value
data_template:
entity_id: input_number.water_softerner_meter_liters
value: 0
#Brine
- alias: "Set water softener start Brine"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Backwash 1st
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Brine
- service: timer.start
entity_id: timer.timer_ws_brine
#Backwash second
- alias: "Set water softener start backwash"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Brine
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Backwash
- service: timer.start
entity_id: timer.timer_ws_backwash
#Rinse
- alias: "Set water softener start Rinse"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Backwash
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Rinse
- service: timer.start
entity_id: timer.timer_ws_rinse
#Fill salt container
- alias: "Set water softener start Fill"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Rinse
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Fill
- service: timer.start
entity_id: timer.timer_ws_fill
#Finish cycles with idle state
- alias: "Set water softener Idle"
initial_state: true
trigger:
- platform: numeric_state
entity_id: sensor.water_softener_power
above: 2.8
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.water_softener_status
state: Fill
action:
- service: input_select.select_option
data:
entity_id: input_select.water_softener_status
option: Idle
- service: input_number.set_value
data_template:
entity_id: input_number.water_softerner_meter_liters
value: 10
- service: mqtt.publish #publish last triggered state
data_template:
topic: "home/lasttrigger/water_softener"
payload_template: "{{ now().strftime('%d.%b %H:%M') }}"
retain: True
#-----------
#LOVELACE CARDS
#-----------
#Notification that regeneration is required
type: conditional
conditions:
- entity: sensor.water_softener_regen
state: 'True'
card:
type: entities
style: |
ha-card {
--ha-card-background: rgba(200, 0, 0, 0.5);
color: white
}
.card-content {
padding: 8px;
}
.card-content > div {
margin: 0 !important;
}
.card-header {
font-size: 18px;
padding: 5px 25px;
font-weight: bold;
}
:host {
--paper-item-icon-color: white;
--secondary-text-color: #A9A9A9
entities:
- entity: input_number.water_softerner_meter_liters
type: 'custom:multiple-entity-row'
icon: 'mdi:beaker-alert-outline'
name: Water softener
secondary_info:
entity: sensor.water_softener_regen
name: 'Dirty: '
state_header: used
entities:
- entity: sensor.water_softener_last_triggered
name: last run
- entity: sensor.water_softener_m3_left
name: left
#Notification when regen is in process with remaining cycle and their times
type: conditional
conditions:
- entity: timer.timer_ws_total
state_not: idle
card:
type: entities
style: |
.card-content {
padding: 8px;
}
.card-content > div {
margin: 0 !important;
}
.card-header {
font-size: 18px;
padding: 5px 25px;
font-weight: bold;
}
.card-header {
font-size: 18px;
padding: 5px 25px;
font-weight: bold;
}
title: Mr. Water Boss working hard
entities:
- conditions:
- entity: timer.timer_ws_backwash1
state_not: idle
row:
entity: timer.timer_ws_backwash1
icon: 'mdi:numeric-1-circle'
name: 'Cycle: Backwash #1'
type: conditional
- conditions:
- entity: timer.timer_ws_brine
state_not: idle
row:
entity: timer.timer_ws_brine
icon: 'mdi:numeric-2-circle'
name: 'Cycle: Brine'
type: conditional
- conditions:
- entity: timer.timer_ws_backwash
state_not: idle
row:
entity: timer.timer_ws_backwash
icon: 'mdi:numeric-3-circle'
name: 'Cycle: Backwash #2'
type: conditional
- conditions:
- entity: timer.timer_ws_rinse
state_not: idle
row:
entity: timer.timer_ws_rinse
icon: 'mdi:numeric-4-circle'
name: 'Cycle: Rinse'
type: conditional
- conditions:
- entity: timer.timer_ws_fill
state_not: idle
row:
entity: timer.timer_ws_fill
icon: 'mdi:numeric-5-circle'
name: 'Cycle: Fill'
type: conditional
- type: section
- entity: timer.timer_ws_total
icon: 'mdi:timer-sand'
name: Total time left (5 cycles)
# card with liters used and m3 left
cards:
- type: entities
entities:
- entity: input_number.water_softerner_meter_liters
type: 'custom:multiple-entity-row'
icon: 'mdi:cup-water'
name: Water softener
secondary_info:
entity: input_select.water_softener_status
name: 'cycle: '
state_header: l used
entities:
- entity: timer.timer_ws_total
name: time left
- entity: sensor.water_softener_m3_left
name: m3 left
style: |
ha-card {
border-radius: 20px
}
.card-header {
font-size: 18px;
padding: 5px 25px;
font-weight: bold;
}
title: Water softener
- entities:
- entity: sensor.water_softener_l_left
max: 4000
min: 0
name: Liters used
height: 8px
decimal: false
positions:
icon: 'off'
indicator: 'off'
tap_action: info
name: 'off'
value: 'off'
style: |
ha-card {
border-radius: 20px
}
.card-content {
padding: 0px 10px 10px 10px;
}
type: 'custom:bar-card'
mode: vertical
type: 'custom:stack-in-card'