Water softener (CLACK WS1) consumed m3/liter monitoring

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


wsoft

Water softener head:

Ingredients needed:

  1. 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.
  2. Smart outlet that has power measurement.
  3. 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” :smiley:
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'

4 Likes

no stupid things, man. Really appreciated. I was looking for something like this :slight_smile:

2 Likes

Thanks for posting your project. I have a GW GXSF30H and I have it connected to an ESP8266 to provide water flow data. I want to provide data when it runs the salt cycle. I have tapped into the relay that will trip for each cycle. It triggers for each cycle(in my case called, Fill, Brine, Rinse, Backwash, Fast Rinse). I’m not using a power sensor. Question is, do I need to know how long each cycle lasts? Thanks

I used timer to show in lovelace how much time left on each cycle and how much time left till finish, but you can use it without timer. If you are not using power sensor, how ESP will now that salt cycle has started?

I have created a binary sensor that trips on the water softeners relay that follows the cam wheel that indicates the cycle it’s in. It will trip 5 times I believe. This signal comes from the ESP8266 device and I have verified it works. I need to verify how many times it trips during the regen cycle. I may need a timer for that last cycle to indicate when the last cycle has finished. The ESP monitors 2 signals…water flow and regen cam wheel.