Bathroom Fan turn off after 2 hours or when moist level is acceptable

Hello everyone,

So I’ve been struggling to get a automation code that does exactly as I need it to do.
The situation is this:

  • I have a (dumb) bathroom fan without a moist sensor.
  • The bathroom fan has a on/off switch in the wall.
  • A shelly sensor now sits between the on/off switch and the power, which is connected to my IoT wifi to be controlled by HA.
  • I have a shelly H&T (Humidity & Temperature) on battery mode (Basically it means it will connect every hour or so to send its status.)

Now on the HA side:

  • I have made a binary sensor that will turn active/inactive when the moist level is at an acceptable level. This one works. Altough I might need to set it to 70% because over the past few days it couldnt achieve less than 65% humidity due to the current climate. Even though the bathroom fan was on for nearly an entire day.
{{ states('sensor.shellyht_[id]_humidity')|float(0) < 65 }}
  • I’ve made several attempts to make it work, but the code gets convoluted and there must be a way to make it simpler… But this is all thats left:
alias: Badkamer Ventilator uitzetten na 2 uur en/of <65% luchtvochtigheid
description: ""
trigger:
  - platform: state
    entity_id:
      - switch.shelly1minig3_[id]_switch_0
    from: "off"
    to: "on"
    for:
      hours: 2
      minutes: 0
      seconds: 0
condition:
  - condition: state
    entity_id: binary_sensor.luchtvochtigheid_acceptabel_niveau
    state: "on"
    for:
      hours: 0
      minutes: 10
      seconds: 0
action:
  - type: turn_off
    device_id: [Shelly Switch Device ID]
    entity_id: [Shelly Switch Button ID]
    domain: switch
mode: single

fyi: The above code does NOT work.

What I want to achieve: When the switch is manually pushed from off to on, I want a timer to run for 2 hours. After those 2 hours, it needs to be checked if the moisture level is at “acceptable level” (see the binary sensor). If its not, it need to wait another hour and check again, after that it needs to turn off.
The reason why I dont want a simple “turn off/on when moisture level is acceptable/-ornot” is because the bathroom fan can be quite loud and we got some ‘light sleepers’ in the house. I dont want it to be on all the night.
(Or maybe someone has an idea where it can turn off/on by itself throughout the day but not run between 01:00 - 08:00? Just an idea…)

I’ve searched the community and there are some absolutely great suggestions, but nothing really to what I require, I think.
I’m sorry if I created a automation request help topic that was exactly as what I needed. Please link it here if it was done before.

I suppose something like this could work.

alias: Badkamer Ventilator uitzetten na 2 uur en/of <65% luchtvochtigheid
description: ""
trigger:
  - platform: state
    id: 2
    entity_id: switch.shelly1minig3_[id]_switch_0
    from: "off"
    to: "on"
    for:
      hours: 2
      minutes: 0
      seconds: 0
  - platform: state
    id: 3
    entity_id: switch.shelly1minig3_[id]_switch_0
    from: "off"
    to: "on"
    for:
      hours: 3
      minutes: 0
      seconds: 0
  - platform: state
    id: dry
    entity_id: binary_sensor.luchtvochtigheid_acceptabel_niveau
    to: "on"
    for:
      hours: 0
      minutes: 10
      seconds: 0
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: 2
          - condition: state
            entity_id: binary_sensor.luchtvochtigheid_acceptabel_niveau
            state: "on"
            for:
              hours: 0
              minutes: 10
              seconds: 0
        sequence:
          - type: turn_off
            device_id: [Shelly Switch Device ID]
            entity_id: [Shelly Switch Button ID]
            domain: switch
      - conditions:
          - condition: trigger
            id: 3
        sequence: 
          - type: turn_off
            device_id: [Shelly Switch Device ID]
            entity_id: [Shelly Switch Button ID]
            domain: switch
      - conditions:
          - condition: trigger
            id: dry
        sequence: 
          - type: turn_off
            device_id: [Shelly Switch Device ID]
            entity_id: [Shelly Switch Button ID]
            domain: switch
mode: single

Thank you!
I will have a look and see if this works.

As an fyi: The code I posted above does NOT work, it does absolutely nothing :wink:
But I couldnt figure it out and that was all that was left…

That is probably because you have junk in the automation.
I highly doubt switch.shelly1minig3_[id]_switch_0 is the correct entity name.
When you do like this all it does is make it worse for you.
If you post your real entities then chances are that you can just copy paste a working automation.
Nobody is going to be able to control your switch just by getting the entity name.

Ah, I just removed the “random number and letters string” purely for safety reasons here, of course I put them back in the actual code. I dont know how dangerous or wise it is to share (unique) ID strings on the open web because I dont know how secure Shelly makes its devices (even though I set the cloud access capabilities to “off” on all Shelly devices).

I get an error when trying to submit the code.
However, I am unable to find the error in question… Is it still possible you can help out?

The error in question:

Message malformed: expected str for dictionary value @ data[‘trigger’][0][‘id’]

Probably this:

id: 2

needs to be

id: "2"

so just make sure you enclose all three id tags with " "

Hmm, sadly I get a new error now:

Message malformed: extra keys not allowed @ data[‘action’][0][‘choose’][0][‘Sequence’]

Ah fudge it, I will just post the entire code:

alias: Badkamer Ventilator uitzetten na 2 uur en/of <65% luchtvochtigheid
description: ""
trigger:
  - platform: state
    id: "2"
    entity_id:
      - switch.shelly1minig3_dcda0ce6b1ec_switch_0
    from: "off"
    to: "on"
    for:
      hours: 2
      minutes: 0
      seconds: 0
  - platform: state
    id: "3"
    entity_id:
      - switch.shelly1minig3_dcda0ce6b1ec_switch_0
    from: "off"
    to: "on"
    for:
      hours: 3
      minutes: 0
      seconds: 0
  - platform: state
    id: "4"
    entity_id:
      - switch.shelly1minig3_dcda0ce6b1ec_switch_0
    from: "off"
    to: "on"
    for:
      hours: 0
      minutes: 10
      seconds: 0 
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: "2"
          - condition: state
            entity_id: binary_sensor.luchtvochtigheid_acceptabel_niveau
            state: "on"
            for:
              hours: 0
              minutes: 10
              seconds: 0
        sequence:
        - type: turn_off
          device_id: a2ef564e5f5a4a8b803d4612e0041296
          entity_id: f2d4aa229be51d73a6bce4e95a46f27c
          domain: switch
      - conditions:
          - condition: trigger
            id: "3"
        sequence:
        - type: turn_off
          device_id: a2ef564e5f5a4a8b803d4612e0041296
          entity_id: f2d4aa229be51d73a6bce4e95a46f27c
          domain: switch
      - conditions:
          - condition: trigger
            id: "4"
        sequence:
        - type: turn_off
          device_id: a2ef564e5f5a4a8b803d4612e0041296
          entity_id: f2d4aa229be51d73a6bce4e95a46f27c
          domain: switch
mode: single

edit: the above code is edited and now is accepted by HA. Thanks to @Hellis81

You have not indented the code correctly under sequence.
And sequence can not be with a capital S

1 Like

Ok I feel really stupid now.
I completely overlooked it. Thank you, its now fixed and the code is accepted. I will test it out tonight and hopefully enjoy the results. :slight_smile:
Thank you for all your time and help @Hellis81 !

I use a delta calc to help turn it off. So on is triggered by hitting a threshold (ex. 80%) and off is triggered when the difference between the shower humidity and bedroom humidity (adjacent room) is less than a delta threshold (ex 7%)

There is also a blueprint that alot of people use

Something like wait_for_trigger sounds perfect for your scenario.

Basically, it waits until your humidity goes back to dry for a predefined timeout, then once that timeout elapses, you choose whether to do something or not, depending on whether you set continue_on_timeout: true or false.

This is an extract from one of my automations. I have tried to replace the entity and trigger IDs with yours, but might have missed something:

action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - 2
        sequence:
          - wait_for_trigger:
              - condition: state
                entity_id: binary_sensor.luchtvochtigheid_acceptabel_niveau
                state: "on"
                for:
                  hours: 0
                  minutes: 10
                  seconds: 0
            timeout:
              hours: 2
              minutes: 0
              seconds: 0
            continue_on_timeout: true
        sequence: (whatever)...

1 Like

Automations that wait is never s good idea.
The automation I posted does the same thing but without waiting.

Agreed 100% but this scenario isn’t some critical function. Worst case, his instance restarts after 1:59 and it will take a further 2 hours before switching off the extractor if his humidity still hasn’t dropped down beyond the threshold at the time.

PS - the from: "off" going to: "on" also won’t trigger if there’s a restart in between. Chances are the sensor will briefly go to “unavailable”, leading back to the same situation as a wait_for_trigger

@LongTimeAgo it might be a good idea to remove the from: lines in your trigger to avoid this, even if you don’t change anything else.

Thank you for the suggestions all.
I’ve tested your code @Hellis81 over the past couple days and it works.
The 10 minute timer worked a little too well. Because the Humidity sensor only updates every hour or so, I used your code to make a 1, 2 and 3 hour “check”.
And this works! Usually after taking a shower the “1 hour” is not enough for the bathroom to fall below 70% humidity, so it usually misses the humidity check of the one hour, but it does catch on the 2 hour. If that does not catch it, it will turn off automatically after 3 hours, which is great.
And the 1 hour is good (enough) for when you use the toilet, lets just say. :wink: