I’m very confused on how you got that. Can you please teach a noob like myself. Can you start/ stop it?
The 2025.2 beta is now available and ships with the initial support for these devices!
Here’s a screenshot showing how the device page looks like on my RV20 Max Plus:
I was very excited to see that vacuums were being added to 2025.2, but after updating saw the update only supports the RV20 Max Plus and RV30 Max. Is there any plan to support the RV10?
Awesome to see this in 2025.2, so encouraging! Thankyou to everyone who has been working on it. I have an RV30C (Roger the Robovac) and looking forward to being able to tell him to start one of his saved routines via HA, maybe in a future update. Also happy to be part of testing if that would help. Thanks again
I also have a rv10. This doesn’t work (yet). Are you guys planning to get this implemented as well?
Thanks for the thanks, it has been a great team effort (as noted in the release notes Release 0.10.0 · python-kasa/python-kasa · GitHub) to get a new device family supported! Given there has been no (issue) reports so far, it’s either working or users are just shy on reporting ![]()
The supported devices list is generated automatically based on information from users, so if you have a device that is working correctly but not listed, feel free to follow the instructions in Contributing — python-kasa documentation to contribute a test fixture file.
My original RV30 Max has experienced a side brush error which made the entire unit unusable within the first 2 months of ownership. I contacted support and started a RMA and now have the replacement.
I’m still facing Home Assistant hangs/restarts when I add the device to my integration. Within some hours the entire system hangs and HA goes offline. It behaves properly when I disable the device from the integration page. I’ve added a ticket : TP-Link RV30 Max vacuum causes HA to run out of memory and crash · Issue #139995 · home-assistant/core · GitHub
Has anyone else experienced this?
My RV30 Max Plus got the Matter update at some point in the last week or so. Exciting!
Good afternoon, I purchased a Tapo RV20 Max robot vacuum cleaner, and I’ve integrated it into HA without any problems using the TP-Link Smart Home integration. For your information, as an amateur HA user, it’s very useful.
Hi,
Firstly … EXCELLENT WORK!!! integration was a breeze!
Quick question?..
Within the Tapo application under rooms tab, created a clean “Preset” called “Dining Kitchen” for the unit to only clean the fining kitchen area as I am planning to schedule cleans for specific rooms in the house on certain days?
Is it possible to send the command from the Home Assistant integration to start that preset?.
I tried the send_command option with the parameter “Dining Kicthen” but receive the error "HomeAssistantError: Validation error: Entity vacuum.rv20 does not support action “vacuum.send_command”?
is this option available? I may be using the wrong syntax.
Keep up the great work!!!
Hello, thank you for your work!
Do you know if there is beta version or plans for support for RV30 Max Plus ?
I just got the RV30 max and I just connected it via Matter no issues really basic stop dock hoover - no mapping as such but enough to automate
I found a workaround automation to control cleaning progress. My purpose is to know when a sepicific area is going to be cleaned in order to remove chairs etc. Tapo gives you the possibility to create shortcuts on iPhone and I used them to launch scheduled cleaning programs from Home Assistant. iOS will send a notification that a program is starting and if you click on the banner it will launch the tapo preset. if can be of help use it!
description: Crea dei reminder per ricordare l'avvio delle pulizie al primo piano
triggers:
- at: "08:59:02"
id: Camera
alias: "Camera: Ma Ve Avvio ore 9,15"
weekday:
- tue
- fri
trigger: time
- at: "10:31:07"
id: Bagno
alias: Bagno Me Avvio ore 10,15
weekday:
- wed
trigger: time
- at: "10:47:28"
id: Tommaso
alias: Tommaso Ma Ve Avvio ore 11,15
weekday:
- tue
- fri
trigger: time
- at: "10:14:43"
id: Giacinta
alias: Giacinta Ogni due Sabati Avvio ore 10,30
weekday:
- sat
trigger: time
- at: "11:26:22"
id: Tinello
alias: Tinello ogni due Sabati Avvio ore 11,40
weekday:
- sat
trigger: time
- at: "10:07:29"
id: Cantina
alias: Cantina Ogni due Sabati Avvio ore 10,20
weekday:
- sat
trigger: time
conditions:
- condition: template
value_template: |
{% if trigger.id in ['Giacinta', 'Tinello'] %}
{{ now().isocalendar().week % 2 == 0 }}
{% elif trigger.id == 'Cantina' %}
{{ now().isocalendar().week % 2 == 1 }}
{% else %}
true
{% endif %}
actions:
- variables:
zona: "{{ schedule[trigger.id].zona }}"
shortcut_asp: "{{ schedule[trigger.id].aspirazione }}"
shortcut_lav: "{{ schedule[trigger.id].lavaggio }}"
- alias: Annuncio avvio aspirazione
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">"Tra 15 minuti inizia l'aspirazione in {{ zona }}.
Preparare l'ambiente per evitare intoppi."</prosody>
data:
type: tts
action: notify.alexa_media
- delay:
hours: 0
minutes: 7
seconds: 30
milliseconds: 0
- alias: Annuncio avvio aspirazione
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">"Tra 7 minuti inizia l'aspirazione in {{ zona }}.
Preparare l'ambiente per evitare intoppi e tenere il telefonino a
portata di mano"</prosody>
data:
type: tts
action: notify.alexa_media
- delay:
hours: 0
minutes: 6
seconds: 15
milliseconds: 0
- alias: Annuncio avvio aspirazione
data:
target: "{{ notifiche_alexa }}"
message: >-
<prosody rate="130%">"Tra poco inizia l'aspirazione in {{ zona }}.
Pronti con il telefonino. Liberare l'ambiente."</prosody>
data:
type: tts
action: notify.alexa_media
- data:
message: Avvio aspirazione in {{ zona }}
data:
shortcut:
name: "{{ shortcut_asp }}"
action: notify.mobile_app_iphone_di_xxxxxx
enabled: true
alias: Richiesta avvio aspirazione tramite notifica xxxxxx
- data:
message: Avvio aspirazione in {{ zona }}
data:
shortcut:
name: "{{ shortcut_asp }}"
action: notify.mobile_app_iphone_di_xxxxxx
enabled: true
alias: Richiesta avvio aspirazione tramite notifica xxxxxxxx
- data:
message: Avvio aspirazione in {{ zona }}
data:
shortcut:
name: "{{ shortcut_asp }}"
action: notify.mobile_app_xxxxxxx
enabled: true
alias: Richiesta avvio aspirazione tramite notifica xxxxxxxx
- alias: Attesa conferma avvio aspirazione
wait_for_trigger:
- entity_id:
- vacuum.robot_primo_piano
to: cleaning
trigger: state
timeout: "00:03:00"
continue_on_timeout: true
- alias: Verifica avvio o timeout aspirazione
choose:
- conditions:
- condition: state
entity_id: vacuum.robot_primo_piano
state: cleaning
sequence:
- alias: Aspirazione avviata correttamente
action: notify.alexa_media
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">Aspirazione avviata in {{ zona
}}.</prosody>
data:
type: tts
default:
- alias: "Timeout: aspirazione annullata"
action: notify.alexa_media
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">Aspirazione in {{ zona }} non confermata entro
3 minuti. Operazione annullata.</prosody>
data:
type: tts
- alias: Crea notifica di timeout
action: persistent_notification.create
data:
title: Automazione Pulizia - Timeout
message: >-
Aspirazione non confermata in {{ zona }} entro 3 minuti. Automazione
annullata.
- alias: Interrompi automazione
stop: Aspirazione non confermata, automazione terminata.
- wait_for_trigger:
- entity_id:
- sensor.robot_primo_piano_cleaning_progress
to: "100"
for:
hours: 0
minutes: 0
seconds: 10
trigger: state
- alias: Annuncio aspirazione completata
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">"Aspirazione completata in {{ zona }}. Inserire il
panno e avviare il lavaggio."</prosody>
data:
type: tts
action: notify.alexa_media
- data:
message: Avvio lavaggio in {{ zona }}
data:
shortcut:
name: "{{ shortcut_lav }}"
action: notify.mobile_app_iphone_di_xxxxxxxx
enabled: true
alias: Richiesta avvio lavaggio tramite notifica xxxxxx
- data:
message: Avvio lavaggio in {{ zona }}
data:
shortcut:
name: "{{ shortcut_lav }}"
action: notify.mobile_app_iphone_di_xxxxxx
enabled: true
alias: Richiesta avvio lavaggio tramite notifica xxxxxx
- data:
message: Avvio lavaggio in {{ zona }}
data:
shortcut:
name: "{{ shortcut_lav }}"
action: notify.mobile_app_xxxxxxx
enabled: true
alias: Richiesta avvio lavaggio tramite notifica xxxxxxx
- alias: Attesa conferma avvio lavaggio
wait_for_trigger:
- entity_id:
- vacuum.robot_primo_piano
to: cleaning
trigger: state
timeout: "00:08:00"
continue_on_timeout: true
- alias: Verifica avvio o timeout lavaggio
choose:
- conditions:
- condition: state
entity_id: vacuum.robot_primo_piano
state: cleaning
sequence:
- alias: Lavaggio avviata correttamente
action: notify.alexa_media
data:
target: "{{ notifiche_alexa }}"
message: |
<prosody rate="130%">Lavaggio avviato in {{ zona }}.</prosody>
data:
type: tts
default:
- alias: "Timeout: lavaggio annullato"
action: notify.alexa_media
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">Lavaggio in {{ zona }} non confermato entro 8
minuti. Operazione annullata.</prosody>
data:
type: tts
- alias: Crea notifica di timeout
action: persistent_notification.create
data:
title: Automazione Pulizia - Timeout
message: >-
Lavaggio non confermato in {{ zona }} entro 3 minuti. Automazione
annullata.
- alias: Interrompi automazione
stop: Lavaggio non confermato, automazione terminata.
- wait_for_trigger:
- entity_id:
- sensor.robot_primo_piano_cleaning_progress
to: "100"
for:
hours: 0
minutes: 0
seconds: 10
trigger: state
- alias: Annuncio lavaggio completato
data:
target: "{{ notifiche_alexa }}"
message: >
<prosody rate="130%">"Pulizia completata in {{ zona }}. Verificare
eventuale manutenzione."</prosody>
data:
type: tts
action: notify.alexa_media
mode: single
variables:
schedule:
Camera:
zona: Camera
aspirazione: Inizio Camera aspirazione
lavaggio: Inizio Camera lavaggio
Bagno:
zona: Bagno
aspirazione: Inizio Bagno aspirazione
lavaggio: Inizio Bagno lavaggio
Sala TV:
zona: Tommaso
aspirazione: Inizio Tommaso aspirazione
lavaggio: Inizio Tommaso lavaggio
Salone:
zona: Tinello
aspirazione: Inizio Tinello aspirazione
lavaggio: Inizio Tinello lavaggio
Ingresso:
zona: Giacinta
aspirazione: Inizio Giacinta aspirazione
lavaggio: Inizio Giacinta lavaggio
Studio:
zona: Cantina
aspirazione: Inizio Cantina aspirazione
lavaggio: Inizio Cantina lavaggio
notifiche_alexa:
- media_player.alexa_cucina
- media_player.alexa_soggiorno
notifiche_ios:
- notify.mobile_app_iphone_di_xxxx
- notify.mobile_app_iphone_di_xxxxxxxxxxxxxxxx
- notify.mobile_app_xxxxxxxxxxxxxxxxxx
See my previous post. I also added a template sensor to let alexa say which are the next cleaning tasks. This is made for two units so you can scale it. Interesting part is that some areas are cleaned every other week and the senso handles it.
- name: "Prossime Pulizie Robot"
unique_id: aecbc378-d85f-4536-92be-2ad74a116cc2
icon: mdi:robot-vacuum
state: >-
{% set today = now().date() %}
{% set base_w = today.isocalendar()[1] %}
{% set now_ts = as_timestamp(now()) %}
{% set pt = namespace(dt=None, zona=None, dt_ts=None) %}
{% set pp = namespace(dt=None, zona=None, dt_ts=None) %}
{% set piano_terra = [
{'giorno': 0, 'ora': '09:15:00', 'stanza': 'Cucina', 'zona': 'Cucina', 'settimane': 1},
{'giorno': 2, 'ora': '09:15:00', 'stanza': 'Cucina', 'zona': 'Cucina', 'settimane': 1},
{'giorno': 4, 'ora': '09:15:00', 'stanza': 'Cucina', 'zona': 'Cucina', 'settimane': 1},
{'giorno': 0, 'ora': '10:15:00', 'stanza': 'Bagno', 'zona': 'Bagno', 'settimane': 1},
{'giorno': 2, 'ora': '10:15:00', 'stanza': 'Bagno', 'zona': 'Bagno', 'settimane': 1},
{'giorno': 4, 'ora': '10:15:00', 'stanza': 'Bagno', 'zona': 'Bagno', 'settimane': 1},
{'giorno': 0, 'ora': '11:15:00', 'stanza': 'Sala TV', 'zona': 'Sala TV', 'settimane': 1},
{'giorno': 2, 'ora': '11:15:00', 'stanza': 'Sala TV', 'zona': 'Sala TV', 'settimane': 1},
{'giorno': 4, 'ora': '11:15:00', 'stanza': 'Sala TV', 'zona': 'Sala TV', 'settimane': 1},
{'giorno': 1, 'ora': '09:15:00', 'stanza': 'Tinello', 'zona': 'Tinello', 'settimane': 1},
{'giorno': 3, 'ora': '09:15:00', 'stanza': 'Tinello', 'zona': 'Tinello', 'settimane': 1},
{'giorno': 5, 'ora': '09:15:00', 'stanza': 'Tinello', 'zona': 'Tinello', 'settimane': 1},
{'giorno': 5, 'ora': '10:30:00', 'stanza': 'Cantina', 'zona': Cantina', 'settimane': 2}
] %}
{% set primo_piano = [
{'giorno': 1, 'ora': '09:15:00', 'stanza': 'Camera Letto', 'zona': 'Camera Letto', 'settimane': 1},
{'giorno': 4, 'ora': '09:15:00', 'stanza': 'Camera Letto', 'zona': 'Camera Letto', 'settimane': 1},
{'giorno': 2, 'ora': '10:15:00', 'stanza': 'Corridoio', 'zona': 'Corridoio', 'settimane': 1},
{'giorno': 1, 'ora': '11:15:00', 'stanza': 'Camera Tommaso', 'zona': 'Camera Tommaso', 'settimane': 1},
{'giorno': 4, 'ora': '11:15:00', 'stanza': 'Camera Tommaso', 'zona': 'Camera Tommaso', 'settimane': 1},
{'giorno': 5, 'ora': '10:30:00', 'stanza': 'Camera Giacinta', 'zona': 'Camera Giacinta', 'settimane': 2},
{'giorno': 5, 'ora': '11:40:00', 'stanza': 'Zona Notte', 'zona': 'Zona Notte', 'settimane': 2},
{'giorno': 5, 'ora': '10:20:00', 'stanza': 'Piano interrato', 'zona': 'Piano interrato', 'settimane': 2}
] %}
{% for s in piano_terra %}
{% set diff = (s.giorno - today.weekday()) % 7 %}
{% set target = today + timedelta(days=diff) %}
{% set date_s = target.strftime('%Y-%m-%d') %}
{% set dt = as_datetime(date_s ~ 'T' ~ s.ora) %}
{% set ts = as_timestamp(dt) %}
{% if (s.settimane == 1 or ((target.isocalendar()[1] - base_w) % s.settimane) == 0) and ts > now_ts %}
{% if pt.dt_ts is none or ts < pt.dt_ts %}
{% set pt.dt = dt %}
{% set pt.zona = s.zona %}
{% set pt.dt_ts = ts %}
{% endif %}
{% endif %}
{% endfor %}
{% for s in primo_piano %}
{% set diff = (s.giorno - today.weekday()) % 7 %}
{% set target = today + timedelta(days=diff) %}
{% set date_s = target.strftime('%Y-%m-%d') %}
{% set dt = as_datetime(date_s ~ 'T' ~ s.ora) %}
{% set ts = as_timestamp(dt) %}
{% if (s.settimane == 1 or ((target.isocalendar()[1] - base_w) % s.settimane) == 0) and ts > now_ts %}
{% if pp.dt_ts is none or ts < pp.dt_ts %}
{% set pp.dt = dt %}
{% set pp.zona = s.zona %}
{% set pp.dt_ts = ts %}
{% endif %}
{% endif %}
{% endfor %}
{% macro day_name(obj) -%}
{% if obj.dt.date() == today %}oggi
{% elif obj.dt.date() == (today + timedelta(days=1)) %}domani
{% else %}{{ obj.dt.strftime('%A') }}{% endif %}
{%- endmacro %}
{# 6) Output forzato #}
{% if true %}
La prossima pulizia di Robottino 1 sarà in {{ pt.zona }} {{ day_name(pt) }}
alle {{ pt.dt.strftime('%H:%M') }}, mentre Robottino 2 pulirà {{ pp.zona }}
{{ day_name(pp) }} alle {{ pp.dt.strftime('%H:%M') }}.
{% endif %} ```
For those who are looking for a quick solution for the RV30 Max Plus, you can do the following: (p.s. you’ll need IFTTT pro for this)
-
In your Tapo app, create shortcuts of the different types of cleaning you’d like to do. For me, I made a shortcut that only cleans the kitchen.
-
Sign up for an IFTTT account and create a new Applet that is triggered by a webhook.
-
Let the Applet execute the Tapo shortcut
-
Call the webhook from Home Assistant by adding this to your configuration.yaml
rest_command:
clean_kitchen:
url: "https://maker.ifttt.com/trigger/your/webhook/url"
- Call the rest_command via an action (e.g. rest_command.clean_kitchen)
Is this ideal? No… Is this secure? Also no… Am I proud of this? Hell no. Does this do the trick until Matter support has been properly introduced? Yep.
- If this was the only applet you wanted to run, would the free level of IFTTT work?
- In Nov 2025, is there a better way?
This has become a not-so-good purchase nowadays…
WHOA !! I have purchased a LOT of TP-Link, Kasa, & Tapo devices. Because they’ve been a good value, & have worked so well with Home Assistant.
I had just purchased an RV30, & was pleased with how well it worked with HA. Then it just stopped, & I hadn’t started troubleshooting yet. But if they’ve broken it, & callously dismiss the issue, that’ll be the last piece of their gear I buy.
The only saving grace might happen if they truly support Matter in a solid fashion.
I was checking here one last time before i was going to buy one. That was a seriously close call after months of research!
