[Automation] Shower detection: trigger when humidity increases in 10 minutes?

Just wanted to say thank you so much for this code.

Super useful. I am using it for a bathroom fan to control humidity as well.

I also modified and made a point that gives me Indoor Air Temp/Outdoor Air Temp Delta-T
As an HVAC technician and an all around physics nerd being able to graph I.A./O.A. Delta-T vs. my AC/Furnace runtime makes me all warm and fuzzy inside.

thank you first for the code. iā€™m not sure if a home assistant update has made "device_class: ā€˜humidityā€™ " depreciated, but i cant seem to configure it correctly. also with the unit of measure as well. Iā€™ve adjusted the device class to ā€˜moistureā€™ , but cant get a unit of measure to stick, so only giving me an on/off sensor.
any pointers would be much appreciated as only using 1 sensor is giving me lots of false readings
this is what its currently looking like.

    sensors:
      bath_humidity_change:
      friendly_name: Bathroom Humidity Change
      value_template: "{{ (states.sensor.bathroom_temp_humidity.state | int ) - (states.sensor.bedroom_temp_humidity.state | int)}}"
        device_class: moisture

Humidity device class should still exist, see here.

Maybe this would help:

    sensors:
      bath_humidity_change:
        friendly_name: Bathroom Humidity Change
        value_template: "{{ (states('sensor.bathroom_temp_humidity') | int ) - (states('sensor.bedroom_temp_humidity') | int)}}"
          device_class: humidity
1 Like

thank you for the reply. i got there in the end!

1 Like

@RyanRayNeff many thx! works like a charmā€¦

Using this value template, I am starting to see error messagesā€¦

Logger: homeassistant.helpers.template
Source: helpers/template.py:1286
First occurred: 9:21:16 PM (5 occurrences)
Last logged: 9:21:17 PM

Template warning: ā€˜intā€™ got invalid input ā€˜unknownā€™ when rendering template ā€˜{{ ( states(ā€˜sensor.your_bathroom_humidity_sensorā€™) | int ) > ( states(ā€˜sensor.bathroom_humidity_statsā€™) | int + 5 ) and ( states(ā€˜sensor.bathroom_humidity_statsā€™) != ā€˜unknownā€™ ) }}ā€™ but no default was specified. Currently ā€˜intā€™ will return ā€˜0ā€™, however this template will fail to render in Home Assistant core 2022.1
Template warning: ā€˜intā€™ got invalid input ā€˜unavailableā€™ when rendering template ā€˜{{ ( states(ā€˜sensor.your_bathroom_humidity_sensorā€™) | int ) > ( states(ā€˜sensor.bathroom_humidity_statsā€™) | int + 5 ) and ( states(ā€˜sensor.bathroom_humidity_statsā€™) != ā€˜unknownā€™ ) }}ā€™ but no default was specified. Currently ā€˜intā€™ will return ā€˜0ā€™, however this template will fail to render in Home Assistant core 2022.1

Soā€¦ is that because during restart the sensor.bathroom_humidity_stats state would be unknown (or is it unavailable?) for a few seconds?

If so, how do I modify my value_template block to remedy the situation?

Recent updates of Home Assistant require the int filter to provide a default value. So both times you see an int in the template above, change this to int(0).

Thanks!

So for other visitors coming to this thread, this is what we should have under the value template block, per the recent updates, at least as of today (24-Feb-2022).

    value_template: >-
      {{ states("sensor.your_bathroom_humidity_sensor") | int(0) >
         states("sensor.bathroom_humidity_stats") | int(0) + 5 and
         states("sensor.bathroom_humidity_stats") != "unknown" }}

I set up the average sensor. What I want is to trigger when there is a quick change over 5% and then to off when it comes back to close to the average. I donā€™t see how the automation does this? Am I missing something?

That is what the binary sensor does and how the fan is controlled.

The binary sensor is on, based on the value template and calculation, when the sensor humidity is greater than the average humidity plus the threshold

The automation then uses this binary sensor to turn on and off the bathroom fan.

Also just posted an update to how Iā€™m doing today, as this method above has changed, albeit only slightly: Quick Bathroom Fan Humidity Switch Control

What confused me is you said you only need the average sensor and the automation.

Hey all! There is another clean way to solve the task.

I am using the statistics component to act based on the change over given time of the humidity in my bathroom. This covers @Domoticon 's original question for a solution for ā€œwhen humidity increases (by x%) within y minutesā€.
The example below does this for turning my fan off but of course this can be adapted to other wishes.

The statistics sensor for humidity stats over the last 5min:

sensor:
  - platform: statistics
    name: Bad Luftfeuchte Statistics 5min Change
    entity_id: sensor.bad_raumsensor_bme280_humidity
    state_characteristic: change
    max_age:
      minutes: 5
    sampling_size: 30

The automation rule in question:

  - alias: Regel Bad LĆ¼ftung aus bei gleichbleibender Luftfeuchte
    trigger:
      - platform: state
        # Trigger for every humidity change
        entity_id: sensor.bad_raumsensor_bme280_humidity
    condition:
      condition: and
      conditions:
        - condition: state  
          # Condition: fan on for at least 5 minutes
          entity_id: switch.bad_luftung
          state: "on"
          for:
            minutes: 5
        - condition: numeric_state
          # Condition: Humidity reached at least 60%
          entity_id: sensor.bad_raumsensor_bme280_humidity
          below: 60
        - condition: numeric_state
          # Condition: Humidity change over the last 5 minutes is smaller than 2%
          entity_id: sensor.bad_luftfeuchte_statistics_5min_change
          above: -2
    action:
      - service: switch.turn_off
        entity_id: switch.bad_luftung

Further automation rules I have defined:

  • Turn the fan on when humidity exceeds 70%
  • Turn the fan off after 60 minutes maximum duration. This is a fallback rule in case the above rule does not work and this even is logged for error handling
4 Likes

Thatā€™s interesting. Is the change under the statistics component the same or similar to the trend component?

Personal experience: a couple of weeks ago I tested using mean under statistics components vs trend components side by side, tweaking parameters, and found that statistics being more reliable and sensitive (to my setup / my humidity sensor.)
Wasnā€™t aware that average_linear being a thing until I see Markā€™s remark above. So thank you Mark, Iā€™m planning to test that also.

Iā€™ve gotten some useful tips from this thread so thanks to all. Iā€™ve noticed that the binary_sensor will turn to 'on' when no shower is running i.e. no humidity changes but just from the ambient temperature in my bedroom, therefore it interferes with my automation logic. Anyone else experience this and have any workaround?

Thanks!

Given 3 months of statistics, I notice that the absolute humidity in my house pretty much follows the humidity so Iā€™ll probably update my automation to enable my fan base of an offset with the external absolute humidity.

Here is the graph - orange is the external absolute humidity, the other ones are elsewhere in my house (when the lines are flat I either had a flat battery or an internet connection issue):

1 Like

Nice one! I had a similar revelation some time ago. The challenge was that, logically speaking, your bathroom humidity canā€™t go below the outside humidity. Therefore, if fan-off-humidity-level is lower than outside-humidity-level, the fan never turns off.

Instead of acting on absolute humidity levels (in relation to the outside humidity) I ended up using the humidity-change-rate - the topic of this thread :slight_smile:

I see that you are talking about enabling the fan, so I guess your use case is slightly different and the logic probably makes sense. Congrats on your discovery :wink:

Iā€™ve been using this for a few months now and the settings seem to suit our use case, at least over the summer!

This is my sensor:

# https://community.home-assistant.io/t/automation-shower-detection-trigger-when-humidity-increases-in-10-minutes/162250/32
  - platform: statistics
    name: Bathroom Humidity Change
    unique_id: dfcf05f4-1d98-45cd-99dd-a91664024257
    entity_id: sensor.bathroomenvironment_humidity
    state_characteristic: change
    max_age:
      minutes: 3
    sampling_size: 30

I use one automation to control the switch, values set in helpers and a countdown timer, again, this seems to work well for us:

- id: '1658846877074'
  alias: Bathroom Extractor
  description: ''
  trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.extractorcountdown
    id: Trigger-TimerFinished
  - platform: numeric_state
    entity_id: sensor.bathroom_humidity_change
    above: input_number.bathroomhumiditychangehigh
    id: Trigger_HumidityUp
  - platform: numeric_state
    entity_id: sensor.bathroom_humidity_change
    below: input_number.bathroomhumiditychangelow
    id: Trigger_HumidityDown
  condition: []
  action:
  - choose:
    - conditions:
      - condition: trigger
        id: Trigger-TimerFinished
      sequence:
      - type: turn_off
        device_id: fd9afcc8e32d00faa76950ffc521b51d
        entity_id: switch.extractor_fan
        domain: switch
    - conditions:
      - condition: trigger
        id: Trigger_HumidityDown
      sequence:
      - type: turn_off
        device_id: fd9afcc8e32d00faa76950ffc521b51d
        entity_id: switch.extractor_fan
        domain: switch
    - conditions:
      - condition: trigger
        id: Trigger_HumidityUp
      - condition: state
        entity_id: input_boolean.holiday
        state: 'off'
      sequence:
      - type: turn_on
        device_id: fd9afcc8e32d00faa76950ffc521b51d
        entity_id: switch.extractor_fan
        domain: switch
      - service: timer.start
        data: {}
        target:
          entity_id: timer.extractorcountdown
      - if:
        - condition: time
          after: '22:00:00'
          before: input_datetime.economy7offtimelocal
        then:
        - service: input_boolean.turn_on
          data: {}
          target:
            entity_id: input_boolean.wettowel
    default: []
  mode: single

Chris

Iā€™m using the following template sensors based on the above information:

In my sensor.yaml file:

# Records Last 3 Mins of Bathroom Humidity
- platform: statistics
  name: Bathroom Humidity Stats
  entity_id: sensor.bathroom_humidity_sensor_2
  state_characteristic: change
  sampling_size: 30
  max_age:
    minutes: 3

In my template.yaml file:

# Showering
- binary_sensor:
  - name: "Showering"
    unique_id: binary_sensor.showering
    icon: 'mdi:shower-head'
    device_class: occupancy
    state: >
      {{ states('sensor.bathroom_humidity_sensor_2') | int(0) >
         states('sensor.bathroom_humidity_stats') | int(0) + 5 and
         states('sensor.bathroom_humidity_stats') != "unknown" }}

I currently have a couple of issues with this code:

  1. Whenever I restart Home Assistant the binary sensor is turned on with a message of: ā€˜Detected triggered by state of Bathroom Humidity Stats changed to 0.0ā€™; and

  2. For some reason, when the statistics sensor had a value of -4.0 it turned on the binary sensor with the message of ā€˜Detected triggered by state of Bathroom Humidity Stats changed to -4.0ā€™

Is anyone able to provide any assistance?

Thanks for your help.

EDIT: I think I need to remove the ā€˜state_characteristic: changeā€™ section of the statistics sensor.

Hey!

First of all, let me suggest to switch to a packages based setup: https://www.home-assistant.io/docs/configuration/packages/

homeassistant:
  packages: !include_dir_named packages

I donā€™t know why this isnā€™t made a default for new users.


Furthermore, Iā€™m not saying the binary sensor is a bad idea (I also like to have ā€œflagsā€ to indicate e.g. showering) but with an automations based approach you would be a lot more empowered to troubleshoot the issues you are seeing. It is certainly better for learning and more scalable, you should consider it.

EDIT: I think I need to remove the ā€˜state_characteristic: changeā€™ section of the statistics sensor.

No I donā€™t think so. I think your state logic is wrong. But that really depends on your use case. What are you trying to accomplish?
Your state template says ā€œhumidity > (humidity_change+5)ā€ which doesnā€™t make sense.

If your wish is to detect showering, you want to either trigger on high humidity. To detect the end of the shower, you can also just look at the absolute humidity. Imho no statistics sensor needed. The tricky part for me was to decide when to turn on and off a ventilation fan. That is where a statistics sensor with the ā€œchangeā€ characteristic was invaluable. Have a look at my automations again

Thanks for this. Iā€™ll look into packages!

I think I did need to change the state_characteristic as this would then default to mean. This way the state logic would be better as it would be comparing an absolute measure of humidity (average over the last hour) against an absolute measure of humidity (current humidity). However, Iā€™ve gone back to using the ā€˜changeā€™ state_characteristic and updated the template binary sensor to:

# Showering
- binary_sensor:
  - name: "Showering"
    unique_id: binary_sensor.showering
    icon: 'mdi:shower-head'
    device_class: occupancy
    state: >
      {{ states('sensor.bathroom_humidity_stats') | int(0) > 5
         and states('sensor.bathroom_humidity_stats') != "unknown"
         and is_state('input_boolean.bathroom_occupancy', 'on')
          }}

I was originally using an automation based approach in NodeRed - using absolute humidity states - that also triggered a counter in Home Assistant. However, I liked the idea of not using absolute humidity values, as these often struggled to pick up different showers within a relatively small space of time, which is why the template sensor relying on change in humidity appealed to me.

Iā€™ll see how this goes!