Xiaomi Vacuum Custom Reminders Part 2

Xiaomi Vacuum Custom Reminders Part 2

In my last post we saw how to set up HA to track and remind us when to empty our vacuum's dust bin and clean the brush head. Now we want to add automation to remind us that it's time to run a cleanup.

Part 2 - Cleanup Reminders

Back-end Setup

First we need a way to track how long it has been since the last full cleaning, then we need automations when that amount of time reaches certain thresholds. The vacuum exposes a date attribute for when the last cleanup was run, but it gets reset on every cleanup. We only want to track full house cleanups.

In Part 1 we created an automation that triggers after a full house cleanup, so we will leverage that automation to set our new variable. First let's create the variable by adding some code to configuration.yaml:

input_datetime: 
    isuck_last_clean_time:
        name: iSuck Last Full Clean
        has_date: true
        has_time: true

Restart HA to create the variable.

Now modify automation.yaml and add a new action so set the variable. Here is the modified automation from Part 1:

- alias: iSuck Large Clean Complete
  trigger:
    platform: state
    entity_id: vacuum.isuck
    from: cleaning
    to: returning
  condition:
  - condition: template
    value_template: '{{ state_attr(''vacuum.isuck'', ''cleaned_area'') > 70 }}'
  action:
  - service: input_datetime.set_datetime
    entity_id: input_datetime.isuck_last_clean_time
    data_template:
      time: '{{ (as_timestamp(state_attr("vacuum.isuck", "clean_start")) | timestamp_custom("%H:%M:%S", true)) }}'
      date: '{{ (as_timestamp(state_attr("vacuum.isuck", "clean_start")) | timestamp_custom("%Y-%m-%d", true)) }}'
  - service: input_boolean.turn_on
    data:
      entity_id: input_boolean.isuck_brush_dirty

The automation will set the custom date variable when the cleanup is complete. Note that we are using the clean_start attribute because we are using our variable to remind when the next cleanup should be started. The clean_start variable is reset when the cleanup starts, but if you have trouble reading this value you could use the now() function and subtract the cleaning_time.

Now we know when the last cleanup was started, but we need a way to track how long it has been since then. The best way to do this is with a template sensor. If you have not set up a sensor before, add the following to your configuration.yaml:

sensor: !include sensors.yaml

Then add a new file in the config folder called sensors.yaml along with the following code:

# Enable clock sensors
- platform: time_date
  display_options:
    - 'time'
    - 'date'
    - 'date_time'
    - 'date_time_iso'
    - 'time_date'
    - 'time_utc'
    - 'beat'
  
- platform: template
  sensors:
    vacuum_cleaning_due:
      friendly_name: Vacuum Cleaning Due
      value_template: >
        {% if (states("vacuum.isuck") != 'docked') %}
          not_due
        {% else %}
        
          {% set now = as_timestamp(states("sensor.date_time_iso")) | float %}
          {% set then = as_timestamp(states("input_datetime.isuck_last_clean_time")) | float %}
          {% set hours_since_last_clean = ((now - then) / 3600) | round(0) %}
          {% if (hours_since_last_clean < 48) %}
            not_due
          {% elif (hours_since_last_clean < 96) %}
            due
          {% else %}
            overdue
          {% endif %}

        {% endif %}

One important detail here is that we are enabling and using the built-in the time_date sensor rather than the now() function, because the sensor approach will ensure that our new template sensor updates its value in real time. Also note that when the vacuum is not docked, we will assign the value "not_due" so that our UI and Automations don't trigger during a cleanup.

The backend setup is now complete and now you can build UI and automations around the new sensors.

New sensors rendered in an Entities Card

Push Notifications

Now we can build some push notifications using our new sensor to remind us when to vacuum the house. Just like in Part 1 we will add shortcut actions and automatic dismissal.

Example push notification (Android Oreo)

First we will add an automation to publish the push notifications. The most obvious approach would be a state trigger that pushes a notification when the sensor changes from "not_due" to "due", but that might lead to notifications arriving at inconvenient times during the day. In order to make the notifications more useful, we'll use a time trigger so that we have control over when the notifications will arrive.

Add to automations.yaml:

- alias: Chore Reminder - Vacuum Cleaning Due Notification
  trigger:
  - platform: time
    at: '08:00:00'
  - platform: time
    at: '16:00:00'
  condition:
  - condition: template
    value_template: '{{ states("sensor.vacuum_cleaning_due") != "not_due"}}'
  - condition: state
    entity_id: person.andrew
    state: home
  action:
  - service: notify.html5_notifications
    data:
      title: iSuck Cleaning Due Today
      message: The house is due for a cleaning today.
      data:
        url: /lovelace/vacuum
        actions:
        - action: start_isuck_cleaning
          title: Start Cleaning
        tag: isuck-cleaning-due

The notifications will publish out at 8AM and 4PM if the cleaning is due. There is also a condition to make sure I am home because the notification does me no good if I'm not home to make sure the floors are clear.

Now we just need two more automations. First, we need to listen for the event that's generated when the notification action is tapped, and second, we need to dismiss the notification when a cleaning is started some other way.

automations.yaml again:

- alias: Vacuum Cleaning Due Notification Complete Event - Start Cleaning
  trigger:
  - event_data:
      action: start_isuck_cleaning
    event_type: html5_notification.clicked
    platform: event
  condition:
  - condition: state
    entity_id: vacuum.isuck
    state: 'docked'
  action:
  - data:
      entity_id: vacuum.isuck
    service: vacuum.start
  
- alias: Vacuum Cleaning Starts - Dismiss Notifications
  trigger:
  - entity_id: vacuum.isuck
    platform: state
    to: cleaning
  action:
  - data:
      data:
        tag: isuck-cleaning-due
    service: notify.html5_dismiss

Note that we added one condition to make sure the vacuum is docked before starting a new cleanup. If the vacuum is undocked, it's either cleaning, stuck for some reason.

Now all of the automations are in place to remind us when to vacuum the house!