Condition of entity NOT being in a certain state for x amount of time

I’ve search the forums high and low but haven’t found this particular question.

Scenario:

My vacuum is set to clean every day at 1PM. But I don’t want it to run if it’s cleaned in the previous 5 hours.

I’ve tried the condition:

alias: Vacuum - Daily Clean
description: ""
trigger:
  - platform: time
    at: "13:00:00"
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.master_presence
        state: Extended Away
  - condition: not
    conditions:
      - condition: state
        entity_id: vacuum.george
        state: cleaning
        for:
          hours: 5
          minutes: 0
          seconds: 0
action:
  - service: vacuum.start
    data: {}
    target:
      entity_id: vacuum.george
mode: single

but I don’t think the “for” will work in this case as it doesn’t matter how long I evaluate for it always returns “true”.

So basically I’m trying to figure out how to evaluate that the state hasn’t been “cleaning” in the last 10 hours as a condition of the automation.

I have tried using states “docked” or “idle” but the problem with that is sometimes the state will change to “unavailable” and then back to “docked” or “idle” which messes up the time. So I’d like to be able to check explicitly for “cleaning” if possible.

The only other thing I can think of trying is setting binary sensor for when the state is “cleaning” and then set a condition for the automation to run when the sensor has been “off” for 5 hours but I would rather a simpler solution if there is one.

Any takers?

If it was me then I would create an automation that triggers from cleaning to docked (or what the parked state is) and set a input datetime with now().

Not only is it rather easy to template the five hours on but also an easy way to see the time

Thanks for the suggestion. I’ll dig into that.

Well I thought I has this problem licked with the binary sensory route but it turns out this isn’t going to work either as I’m falling victim to the problem of the sensor going into an unknown state when I restart home assistant. If that happens it screws up the time elapsed between docked to cleaning.

So I’ll be taking a closer look at @Hellis81 's suggestion.

I would suggest you can use a timer that (re)starts whenever the vacuum redocks, and have a duration of 5 hours with it. In every piece of logic you have that would command it to leave the dock, add logic to not allow that to happen if the timer is not in a state of idle (meaning it had not yet finished). Thoughts? I use timers that are (re)started by motion sensors, and then have lights that go on when the timers start and off when they are finished. Therefore there’s no issue with lights going off if people are in the room because it won’t happen. Then I also got a little fancier and used input_number variables (for timer duration) set as sliders and then have the code refer to them any time I (re)start a timer, so that from the dashboard (usually on my phone in the HA app) I can easily change the length of time for each of the timers without having to look through the code. You could do the same to change your 5 hours and also you could have a switch on your dashboard that would disable or override the restriction (for that I have input_select helpers (drop-downs on the dashboard with just two choices, “Enabled” and “Disabled”) to enable and disable automations from my dashboard (as you get fancier you just have to go back and add the state of all of those everywhere in the logic, and then more automations for what to do when you enable or disable something.) Of course with my situation I have to consider if someone manually turns off the light, then the timer should also be stopped, etc. and you might run into one off cases where you need to add code for one-off types of scenarios. But I love the timers and my sliders for all the lights in my home. Most of us never bother turning lights on or off any more (and we save alot of power at the same time!) - when anyone goes into a room, if the lights are not already on, they go on - and a short time after everyone has left a room they turn off. I’ve slowly replaced wall light switches with smart dimmers (Belkin Wemo which are supported by HA) and for all the lamps plugged into the wall for power - into smart outlets (Belkin Wemo Smart Plugs which are all supported by HA). I’ve also got a weather station tied into HA and some lights I make brighter or dimmer depending not upon the time of day but how bright it is outside (inverse relationship). If you are able to control the route your vacuum takes and have very sophisticated motion/presence sensors in the home - maybe you can freak someone out by remotely chasing them around your home with the vacuum cleaner… :slight_smile:

Quick question - how does the smart vacuum (roomba or whatever it is) deal with a possible dog poop scenario? I’ve hard of situations wher the roomba smeared it all over the place (ugh!)?

What happens when a timer is running and you restart Home Assistant?
Honest question, I don’t know.

Five hours is a long time to have “delay” if the timer does not survive the restart.

They elegently handle it. The time left is saved somewhere and when the app is restarted, the timers continue on from the same amount of time left. I have added some automations that on startup if a light is on and the related timer is idle, to continue the countdown where it left off, but those are not even called I believe. I had set my timers up directly in configuration.yaml however, not in the UI - note the restore variable (sorry, spacing doesn’t work here - replace each ‘x’ with a space in your code):

timer:
xxdining_room_chandelier_timer:
xxxxduration: ‘00:15:00’
xxxxname: Dining Room Chandelier Timer
xxxxrestore: true

So far I’ve managed to solve this with an input_boolean helper that gets turned on when the vacuum is cleaning and off when it’s docked. So far I haven’t run into it being in any other state than on or off like I was running into with the template binary sensor.

But I’ll also take a look your timer suggestion, thanks.

As for how the vacuum handles animal messes, I don’t have dog so can’t say how well it works around that.

You should just need to store the last clean time in a datetime_helper. Then you can just create a condition that it doesn’t run if its less than x hours since the time in that helper. When it’s done cleaning, you update that helper.

A timer would work as well but I wouldn’t want that thing counting down all the time as I do have timers in my lovelace…

Reliving this because setting the input_boolean and running the automation with the condition of the input_boolean being off for X amount of time is behaving very inconsistently. Sometimes the condition is met and sometimes it’s not and I’m having a hard time diagnosing why that’s the case from the automation trace.

I’ve created an automation to set the date/time to the time the start vacuuming automation is run.

But can you give any hints on how to format the condition checking if the ten hours have elapsed?

Here is my automation to set the date_time:

alias: Vacuum - Cleaning - Set Current Time
description: ""
trigger:
  - platform: state
    entity_id:
      - vacuum.george
    to: cleaning
condition: []
action:
  - service: input_datetime.set_datetime
    data:
      datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
    target:
      entity_id: input_datetime.vacuum_cleaning_start
mode: single

And my automation to run the vacuum cleaning job currently checking against the input_boolean. Would like to check it against the input_datetime.vacuum_cleaning_start for ten hours elapsed:

alias: Vacuum - Daily Clean
description: ""
trigger:
  - platform: time
    at: "20:00:00"
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.master_presence
        state: Extended Away
  - condition: state
    entity_id: input_boolean.vacuum_cleaning
    state: "off"
    for:
      hours: 10
      minutes: 0
      seconds: 0
action:
  - service: vacuum.start
    data: {}
    target:
      entity_id: vacuum.george
mode: single

I’ve solved (I hope) for the time being by using the UNIX timestamp and comparing against current time in UNIX format to find out time elapsed:

{{ now().timestamp() - state_attr('input_datetime.vacuum_cleaning_start', 'timestamp') > 36000 }} 

I’m sure there’s a way to do it by directly comparing the date/time stored in the input_datetime with current time but this seems to work ok.

alias: Vacuum - Daily Clean - Test
description: ""
trigger:
  - platform: time
    at: "20:00:00"
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.master_presence
        state: Extended Away
  - condition: template
    value_template: >-
      {{ now().timestamp() - state_attr('input_datetime.vacuum_cleaning_start',
      'timestamp') > 36000 }} 
action:
  - service: vacuum.start
    data: {}
    target:
      entity_id: vacuum.george
  - service: input_datetime.set_datetime
    target:
      entity_id: input_datetime.vacuum_cleaning_start
    data:
      datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
mode: single

1 Like