How do you automate your vacuum for emptying the bin?

Hey guys,

I was wondering what you guys are doing in order to automate the vacuum a bit more. currently i have several automations for the start of the two robots that I have. I still have to remember to empty the bin after every other run and of course I’d like to automate that as well by sending the robot to bin.

I think it either has to be done by calculating the total number of runs since it was last emptied. I think it would be better though to use the total m² cleaned since the bin was last emptied since 1 cleaning run of the kitchen fills the bin way less than a complete run.

Here is what I’m thinking of implementing:

  1. Upon returning state of the vacuum add the value of last clean run to an input_number sensor
  2. Once somebody is near the bin (triggered by light turning on or google home starts playing) AND the value of the input_number sensor is higher than, let’s say, 120, drive the vacuum to the bin and reset the input_number to 0.

How are you guys doing this?

2 Likes

It runs when the last person left the house on werkdays.

- alias: "Vacuum Start when away"
  trigger:
    - platform: state
      entity_id: switch.anwesend
      to: 'off'
      for:
        minutes: 15
  condition:
    - condition: state
      entity_id: input_boolean.vacuum_enabled
      state: 'on'
    - condition: state
      entity_id: vacuum.roberta
      state: 'docked'
      for:
        hours: 8
    - before: '14:00:00'
      condition: time
      weekday:
        - mon
        - wed
        - fri
  action:
    - service: script.vacuum_start
# Start vacuum when someone still at home at 1400
- alias: "Vacuum Start when not away"
  trigger:
    - platform: time
      at: "14:00:10"
  condition:
    - condition: state
      entity_id: input_boolean.vacuum_enabled
      state: 'on'
    - condition: state
      entity_id: switch.gaste_da
      state: 'off'
    - condition: state
      entity_id: binary_sensor.workday
      state: 'on'
    - condition: state
      entity_id: vacuum.roberta
      state: 'docked'
      for:
        hours: 8
    - condition: time
      weekday:
        - mon
        - wed
        - fri
  action:
    - service: script.vacuum_start

If it has run during the day it drives to a place near the dustbin.

- alias: "Vacuum Empty Trash"
  trigger:
    - platform: state
      entity_id: switch.anwesend
      to: 'on'
      for:
        minutes: 20
  condition:
    - condition: numeric_state
      entity_id: sensor.vaccum_runtime_24h
      above: 0.5
    - condition: time
      after: '08:00:00'
      before: '21:00:00'
  action:
    - service: script.vacuum_go_trash_can 

vacuum_go_trash_can:
  alias: "Fahre zum Mülleimer"
  sequence:
    - service: notify.alexa_media
      data_template:
        target:
          - media_player.echo_wohnen
        data:
          type: announce
        message: "Bitte den Staubsaugerbeutel leeren."
    - delay: '00:00:10'
    - service: vacuum.send_command
      data:
        entity_id: vacuum.roberta
        command: app_goto_target
        params: [20000, 29400]
2 Likes

I count the number of times its vacuumed and then recommend (via push message) when to empty it. I dont have the ability to send it to the bin unfortunately.

After three cleaning circles my vacuum drives to the bin in the kitchen und a permanent notifiction is created.
When I get home a TTS notification reminds me to empty the bin.

After I have emptied the bin and I have discharged the notification the vaccum drives back to the docking station.

I was thinking on measuring the cleaned area and empty the bin after xx m². But I do not see a real advantage to my current automations.

Hi! This is exactly what I’m trying to do but still with no luck…
I want to receive a notification every 3 times the robot vacuums the house.

Here’s my automation:

- id: '1593188318134'
  alias: Esvaziar aspirador
  description: ''
  trigger:
  - entity_id: vacuum.aspirador
    platform: state
    to: returning
  condition:
  - condition: template
    value_template: '{{ (trigger.to_state.attributes.cleaning_count / 3)|int > (trigger.from_state.attributes.cleaning_count
      / 3)|int }}'
  action:
  - data:
      message: O deposito do aspirador deve estar cheio porque ja aspirou 3 vezes
        seguidas!
      title: Limpar aspirador
    service: notify.mobile_app_oneplus_a6013

I’m not sure if I’m using the template correctly here…
Can you guys share your automation @dennis84de @callifo ?

Thanks in advance

My vacuum automations are a little complex so the small part of it you actually want might be a little difficult. Hopefully you can pick something out of it.

I want to vacuum every certain number of days I am home, and not on a fixed schedule. I check if people are home at midnight, and then increment a counter for the number of days at home. Then each day, when no one is home, check if a minimum of x days has passed, then run.

I have a vacuum script that sets off the vacuum that also increments an input_number, which then a notification automation can check if this is above 1 (e.g. 2 vacuums since last empty).

I use the vacuum script as when my vacuum runs I need to disable my home alarm as it sets off the PIRs. Then after its complete, it turns the alarm on again.

The basis of it is,

[configuration]
input_number:
  last_vacuumed:
    name: Days since last vacuum
    min: 0
    max: 365
    step: 1
  days_between_vacuuming:
    name: Days between vacuuming
    min: 1
    max: 14
    step: 1
  vacuum_count_last_emptied:
    name: Vacuum Count Last Emptied
    min: 0
    max: 365
    step: 1
sensor:
  - platform: template
    sensors:
      vacuum_next:
        friendly_name: 'Next Vacuum'
        value_template: "{{(states('input_number.days_between_vacuuming') | int) - (states('input_number.last_vacuumed') | int)}}"
        entity_id:
          - input_number.days_between_vacuuming
          - input_number.last_vacuumed
[automations]
- id: last_vacuumed_increment
  alias: 'Vacuum Cleaner - Increment since last vacuumed'
  trigger:
    - platform: time
      at: '00:00:00'
  condition:
    - condition: numeric_state
      entity_id: sensor.vacuum_next
      above: 0
    - condition: state
      entity_id: group.people_status
      state: 'home'
  action:
    - service: input_number.increment
      entity_id: input_number.last_vacuumed

- id: vacuum_schedule
  alias: 'Vacuum Cleaner - Vacuum every 3 days'
  trigger:
    - platform: time_pattern
      hours: "/1"
  condition:
    - condition: state
      entity_id: group.people_status
      state: 'not_home'
    - condition: template
      value_template: "{{ (as_timestamp(now()) | float - (as_timestamp(states.group.people_status.last_changed) | default(0) | float )) > 2700.0 }}"
    - condition: time
      after: '09:00:00'
      before: '20:00:00'
    - condition: state
      entity_id: vacuum.dusty
      state: 'docked'
    - condition: template
      value_template: "{{ states('input_number.last_vacuumed') | int >= states('input_number.days_between_vacuuming') | int }}"
  action:
    - service: script.vacuum_now

- id: vacuum_alarm_on
  alias: 'Vacuum Cleaner - Run whilst away, turn alarm back on'
  trigger:
    - platform: state
      entity_id: vacuum.dusty
      to: 'docked'
  condition:
    - condition: state
      entity_id: group.people_status
      state: 'not_home'
    - condition: state
      entity_id: alarm_control_panel.house_alarm
      state: 'disarmed'
  action:
    - service: alarm_control_panel.alarm_arm_away
      entity_id: alarm_control_panel.house_alarm
- id: empty_vacuum_notification
  alias: 'Notification - Empty Vacuum'
  trigger:
    - platform: time
      at: '19:30:00'
    - platform: time
      at: '20:30:00'
    - platform: time
      at: '21:30:00'
    - platform: time
      at: '22:30:00'
  condition: 
    - condition: state
      entity_id: group.people_status
      state: 'home'
    - condition: template
      value_template: "{{ ((as_timestamp(now()) | float) - (as_timestamp(state_attr('automation.notification_empty_vacuum','last_triggered')) | default(0) | float )) | int > 21600 }}"
    - condition: numeric_state
      entity_id: input_number.vacuum_count_last_emptied
      above: 1
  action:
    - delay: "{{ range(0, 15)|random }}"
    - wait_template: "{{ is_state('input_boolean.script_send_push_message','off') }}"
      timeout: 00:02:00
    - service: script.send_push_message
      data_template:
        to_user: nick
        urgent: false
        message: 'Empty the vacuum cleaner.'
    - service: input_number.set_value
      data_template:
        entity_id: input_number.vacuum_count_last_emptied
        value: 0
[script]
vacuum_schedule:
  sequence:
    - service: input_number.increment
      entity_id: input_number.vacuum_count_last_emptied
    - service: neato.custom_cleaning
      entity_id: vacuum.dusty
      data:
        mode: 2
        navigation: 1
        category: 2
    - service_template: >
        {% if is_state('alarm_control_panel.house_alarm','armed_away') or is_state('alarm_control_panel.home','armed_away') %}
        alarm_control_panel.alarm_disarm
        {% else %}
        script.do_nothing
        {% endif %}
      data:
        entity_id: alarm_control_panel.house_alarm
        code: xxxx

vacuum_today:
  sequence:
    - service: input_number.set_value
      data_template:
        entity_id: input_number.last_vacuumed
        value: "{{ states('input_number.days_between_vacuuming') | int }}"

vacuum_now:
  sequence:
    - service: script.vacuum_schedule
    - service: input_number.set_value
      data:
        entity_id: input_number.last_vacuumed
        value: 0

So the part that counts the number of vacuums is just a launcher script to start vacuuming incrementing a input_number. Ignore the push message script, it just allows me to filter push notifications and TTS to prevent it going off when someone is in bed; you can just replace the whole action part with just a standard push notification.

2 Likes

Thank you so much for taking the time and explaining your automation. I’ll look into it with more attention later and try to get something out of it!

I have an counter which is decremented after cleaning. When the counter reaches 0 the vacuum goes to the kitchen and I get a notification when I come home.
When I discharge the notification the vacuum drives back to the docking station.

counter:
  empty_bin:
    name: Empty bin
    icon: mdi:delete-empty
    initial: 3
    step: 1

automation:
  - alias: "Vacuum - Finished"
    trigger:
      - platform: state
        entity_id: vacuum.xiaomi_vacuum_cleaner
        from: 'returning'
        to: 'docked'    
    condition:
      - condition: state
        entity_id: input_boolean.staubsauger_automatische_reinigung_gestartet
        state: 'on'      
    action:
      - service: counter.decrement
        entity_id: counter.empty_bin
      - service: input_boolean.turn_off
        entity_id: input_boolean.staubsauger_automatische_reinigung_gestartet     

  - alias: "Vacuum - Empty bin"
    trigger:
      - platform: numeric_state
        entity_id: counter.behaelter_leeren
        below: 1
    action:
      - service: persistent_notification.create
        data:
          title: "Staubsauger"
          message: "Der Staubsaugerbehälter muss geleert werden."
          notification_id: staubsauger_leeren
      - service: vacuum.send_command
        data:
          entity_id: vacuum.xiaomi_vacuum_cleaner
          command: app_goto_target
          params: [33463,24839]

  - alias: "Vacuum - Bin emptied"
    trigger:
      - platform: event
        event_type: call_service
        event_data:
          domain: persistent_notification
          service: dismiss      
    condition:
      - condition: template
        value_template: '{{ trigger.event.data.service_data.notification_id == "staubsauger_leeren" }}'
    action:
      - service: counter.reset
        entity_id: counter.behaelter_leeren
      - service: vacuum.return_to_base
        entity_id: vacuum.xiaomi_vacuum_cleaner

  - alias: "Coming home - Start greetings"
    trigger:
      - platform: state
        entity_id: binary_sensor.tuersensor
        to: 'off' 
    condition:
      - condition: state
        entity_id: input_boolean.zu_hause_begruessung
        state: 'on'       
    action:
      - delay: '00:00:30'
      - service: !secret tts_service
        data_template:
          message: >-
            "Hallo Dennis. Willkommen zu Hause."
            
            {% if is_state('counter.behaelter_leeren', '0') %}
              "Der Staubsaugerbehälter muss geleert werden."
            {% endif %}

            ...
1 Like

This is perfect!
Great job!

Thank you!

I configured it this way. Check the remainder of the clean interval divived by 3 is 0

- id: '1598738245510'
  alias: Robbie stofbak legen
  description: Herinnering om Robbie zijn stofbak te legen na 3 keer schoonmaken
  trigger:
  - platform: template
    value_template: '{{ state_attr(''vacuum.robbie'', ''cleaning_count'') % 3 | float
      == 0  }}'
  condition: []
  action:
  - data:
      message: Robbie zijn stofbak moet geleegd worden.
      title: Robbie Stofbak
    service: notify.mobile_app_moto_g_5_plus
  mode: single

When is the cleaning count incremented?
After a complete cleaning cycle or after a spot cleaning too?

It increments after a clean up and spot cleaning is not counting.

This is what I use in Node-Red if anyone is interested…

I have it to go to the bin every 5 runs based on the state going from cleaning>idle or cleaning>returning so it works on spot/zone cleaning and a regular run.
I know this is not the best way because goto target command changes the status to cleaning (at least on S5) therefore will increase the clean count but I have it so it can only do this once between docking so even if it goes back to idle and then you start spot cleaning it wont increase the count again.
its set to notify Alexa if I’m home and notify the app if I am not.

[{"id":"e01fdcb5.09304","type":"api-call-service","z":"9864b332.ab508","name":"Empty Vacuum Announcement","server":"1b082828.a31468","version":1,"debugenabled":false,"service_domain":"notify","service":"alexa_media_living_room_echo_plus","entityId":"","data":"{\"message\":\"Please empty the vacuum\",\"data\":{\"type\":\"announce\"}}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":2410,"y":860,"wires":[[]]},{"id":"9778b5b9.f50228","type":"function","z":"9864b332.ab508","name":"Reset The Clean Counter (After 5 Runs)","func":"msg.reset = true;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1440,"y":800,"wires":[["b2da08ea.65bf08"]]},{"id":"50ae9228.58494c","type":"function","z":"9864b332.ab508","name":"Clean count decrease","func":"msg.decrement = 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1160,"y":880,"wires":[["b2da08ea.65bf08"]]},{"id":"b2da08ea.65bf08","type":"counter","z":"9864b332.ab508","name":"","init":"5","step":1,"lower":"","upper":"","mode":"decrement","outputs":"1","x":1380,"y":880,"wires":[["a8557782.491ef8"]]},{"id":"a8557782.491ef8","type":"switch","z":"9864b332.ab508","name":"","property":"count","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":1510,"y":880,"wires":[["9778b5b9.f50228","a3bad66b.355408"]]},{"id":"cd983b0a.75d8e8","type":"inject","z":"9864b332.ab508","name":"decrement","repeat":"","crontab":"","once":false,"topic":"","payload":"","payloadType":"date","x":1220,"y":980,"wires":[["b2da08ea.65bf08"]]},{"id":"325abad0.66acc6","type":"inject","z":"9864b332.ab508","name":"increment","repeat":"","crontab":"","once":false,"topic":"","payload":"","payloadType":"date","x":1200,"y":940,"wires":[["b2da08ea.65bf08"]]},{"id":"b1a1c792.a0ad98","type":"inject","z":"9864b332.ab508","name":"Reset Both Counters","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"date","x":1110,"y":820,"wires":[["8f2c7778.f13498","b2da08ea.65bf08"]]},{"id":"a3bad66b.355408","type":"api-call-service","z":"9864b332.ab508","name":"Goto Bin","server":"1b082828.a31468","version":1,"debugenabled":false,"service_domain":"vacuum","service":"send_command","entityId":"vacuum.chip","data":"{\"command\":\"go_to\",\"params\":{\"spot_id\":\"KitchenBin\"}}","dataType":"json","mergecontext":"","output_location":"payload","output_location_type":"msg","mustacheAltTags":false,"x":1660,"y":880,"wires":[["4ae2006f.46bae"]]},{"id":"9f943d76.951be","type":"ha-wait-until","z":"9864b332.ab508","name":"","server":"1b082828.a31468","outputs":1,"entityId":"vacuum.chip","entityIdFilterType":"exact","property":"state","comparator":"is","value":"idle","valueType":"str","timeout":"0","timeoutType":"num","timeoutUnits":"seconds","entityLocation":"payload","entityLocationType":"msg","checkCurrentState":true,"blockInputOverrides":true,"x":2020,"y":900,"wires":[["c79c55.a139d3a8"]]},{"id":"4ae2006f.46bae","type":"stoptimer","z":"9864b332.ab508","duration":"5","units":"Second","payloadtype":"num","payloadval":"0","name":"(Wait for Positioning)","x":1840,"y":860,"wires":[["9f943d76.951be"],[]]},{"id":"c79c55.a139d3a8","type":"api-current-state","z":"9864b332.ab508","name":"Home?","server":"1b082828.a31468","version":1,"outputs":2,"halt_if":"home","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"person.xalies","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":2180,"y":900,"wires":[["e01fdcb5.09304"],["be75ee3f.8298"]]},{"id":"be75ee3f.8298","type":"api-call-service","z":"9864b332.ab508","name":"App Notification - Empty Vacuum","server":"1b082828.a31468","version":1,"debugenabled":false,"service_domain":"notify","service":"mobile_app_pixel_3","entityId":"","data":"{\"message\":\"Vacuum waiting to be emptied\",\"title\":\"Empty Vacuum\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":2420,"y":920,"wires":[[]]},{"id":"400771d0.528cd","type":"trigger-state","z":"9864b332.ab508","name":"Vacuum State (Cleaning>Idle)","server":"1b082828.a31468","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"vacuum.chip","entityidfiltertype":"exact","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"idle","propertyValue":"new_state.state"}],"outputs":3,"customoutputs":[{"messageType":"default","messageValue":"","messageValueType":"json","comparatorPropertyType":"previous_state","comparatorType":"is","comparatorValue":"cleaning","comparatorValueDataType":"str","comparatorPropertyValue":"old_state.state"}],"outputinitially":false,"state_type":"str","x":130,"y":900,"wires":[[],[],["708be626.0cf168"]]},{"id":"43e7b87c.9c37c8","type":"function","z":"9864b332.ab508","name":"Reset idle counter","func":"msg.reset = true;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":960,"wires":[["8f2c7778.f13498"]]},{"id":"708be626.0cf168","type":"function","z":"9864b332.ab508","name":"msg object","func":"msg.decrement = 1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":390,"y":880,"wires":[["8f2c7778.f13498"]]},{"id":"8f2c7778.f13498","type":"counter","z":"9864b332.ab508","name":"","init":"1","step":1,"lower":"","upper":"","mode":"decrement","outputs":"1","x":580,"y":880,"wires":[["760a4513.e54d2c"]]},{"id":"760a4513.e54d2c","type":"switch","z":"9864b332.ab508","name":"Pass though only one count (until reset at dock)","property":"count","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":840,"y":880,"wires":[["50ae9228.58494c"]]},{"id":"44f08fae.5e58d","type":"server-state-changed","z":"9864b332.ab508","name":"Reset when docked","server":"1b082828.a31468","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"vacuum.chip","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"docked","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":90,"y":960,"wires":[["43e7b87c.9c37c8"],[]]},{"id":"2a5f0281.6b0dde","type":"trigger-state","z":"9864b332.ab508","name":"Vacuum State (Cleaning>Returning)","server":"1b082828.a31468","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"vacuum.chip","entityidfiltertype":"exact","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"returning","propertyValue":"new_state.state"}],"outputs":3,"customoutputs":[{"messageType":"default","messageValue":"","messageValueType":"json","comparatorPropertyType":"previous_state","comparatorType":"is","comparatorValue":"cleaning","comparatorValueDataType":"str","comparatorPropertyValue":"old_state.state"}],"outputinitially":false,"state_type":"str","x":150,"y":840,"wires":[[],[],["708be626.0cf168"]]},{"id":"1fcec11e.e2cf2f","type":"comment","z":"9864b332.ab508","name":"Goto Bin: Every 5 Runs","info":"","x":100,"y":760,"wires":[]},{"id":"1b082828.a31468","type":"server","z":"","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Edit: noticed a mistake in mine, fixed here

1 Like

I know post is a bit old but might not be worth opening a new thread… so i’m asking here

I set the above up using node-red so that after x amount of cleaning my roborock s50 goes next to the bin and waits there for me to easily clean the bin.

However as you all know every now and then you need to wash the filter …however it seems I can’t send my s50 back to the dock without the filter (since it’s drying) as I get an error 9 that it’s missing the bin/filter.

is there way to overcome this ?