Il robot di casa è un Dreame che aspira e lava, con la stazione base che lava il panno da sola. È collegato a Home Assistant con l'integrazione comunitaria dreame_vacuum e lo comando anche da WhatsApp: come funzionano avvisi e comandi «robot …» lo racconto in robot Dreame su WhatsApp. Il messaggio arriva al gateway, il gateway lo passa a un webhook di Home Assistant e lo script robot_comando capisce cosa voglio e risponde. Possono usarlo solo i mittenti autorizzati che hanno la categoria «robot», come spiego in ruoli Admin e Utente con categorie.
Un giorno scrivo «robot pulisci». Il robot parte, pulisce la stanza in cui si trova, al massimo un'altra, e rientra. La casa era tutta da fare.
🔎 L'indagine
Prima di toccare qualcosa sono andato a guardare cosa era successo davvero. Il recorder di Home Assistant tiene la storia di ogni entità, attributi compresi: ho letto quella del robot (stato e attributi started, paused, active_segments) e quella del sensore degli errori.
| Quando | Stato del robot | Cosa dicono gli attributi |
|---|---|---|
| Mattino | cleaning | Parte la pulizia programmata di tutta la casa |
| Poco dopo | error | Errore dell'acqua: serbatoio pulito vuoto |
| Dopo | error | Altro errore dell'acqua: serbatoio sporco pieno |
| Fino al mio messaggio | paused | started ancora vero: l'attività non è mai stata chiusa |
| «robot pulisci» | cleaning | Riprende la stessa attività e pulisce solo le stanze rimaste |
| Fine | returning, poi docked | Rientra alla base |
Il pezzo che mancava era nel comando. Lo script chiamava vacuum.start, e ho aperto il codice dell'integrazione per vedere cosa fa: start() vuol dire «avvia o riprendi». Se c'è un'attività in pausa la riprende. Quindi il robot non stava sbagliando niente: finiva la pulizia del mattino dal punto in cui si era fermato.
⚠️ La causa, in una riga
vacuum.start non vuol dire sempre «pulizia nuova». Con un'attività avviata e in pausa, la riprende.
🛠️ La correzione
Adesso «robot pulisci» vuol dire sempre una pulizia nuova. Se trova un'attività aperta (avviata, in pausa, in errore o in rientro) prima la chiude, aspetta che il robot lo confermi, e solo dopo riparte: con vacuum.start per tutta la casa, oppure con dreame_vacuum.vacuum_clean_segment per le stanze nominate, come «robot pulisci cucina e bagno».
- variables:
attivita_aperta: >-
{{ state_attr('vacuum.robot', 'started') == true
or states('vacuum.robot') in ['paused', 'error', 'returning'] }}
- if: "{{ attivita_aperta }}"
then:
- action: vacuum.stop
target:
entity_id: vacuum.robot
- wait_template: "{{ state_attr('vacuum.robot', 'started') != true }}"
timeout: "00:00:30"
continue_on_timeout: true
- delay: "00:00:03"
- if: "{{ stanze | count > 0 }}"
then:
- action: dreame_vacuum.vacuum_clean_segment
target:
entity_id: vacuum.robot
data:
segments: "{{ stanze | map(attribute='id') | list }}"
else:
- action: vacuum.start
target:
entity_id: vacuum.robot
Poi lo script aspetta, fino a 45 secondi, che lo stato diventi cleaning. Il robot spesso lava prima il panno nella base: anche quella fase per Home Assistant è cleaning, e per me conta come partito.
- wait_template: "{{ is_state('vacuum.robot', 'cleaning') }}"
timeout: "00:00:45"
continue_on_timeout: true
- variables:
partito: "{{ wait.completed }}"
errori:
water_tank: "serbatoio dell'acqua pulita vuoto"
dirty_water_tank: "serbatoio dell'acqua sporca pieno"
battery_low: "batteria scarica"
codice: "{{ states('sensor.robot_error') }}"
errore: "{{ errori.get(codice, codice) }}"
La risposta su WhatsApp racconta l'esito vero, non quello sperato. Se il robot è partito, la risposta lo dice e avvisa che una pulizia interrotta è stata annullata. Se non è partito, mostra stato, batteria ed errore tradotto in italiano dalla piccola mappa qui sopra.
Esempio: pulizia nuova dopo una programmata rimasta in pausa
Esempio: il robot non parte per un errore dell'acqua
«Robot riprendi» resta l'unico comando che riprende l'attività vecchia, con vacuum.start come prima. Così la scelta è mia, non del robot.
🧽 I nuovi comandi per la stazione base
Già che c'ero ho aggiunto i comandi che mi mancavano. Per lavare il panno scrivo «robot autopulizia», ma vanno bene anche «pulisci base» e «lava panno». Poi «robot asciuga» per l'asciugatura del panno e «robot svuota» per lo svuotamento automatico.
C'è un dettaglio importante. I pulsanti che l'integrazione crea per queste funzioni si comportano come interruttori: premerli durante un lavaggio lo ferma. Un secondo messaggio uguale, scritto per sicurezza, annullerebbe il primo. Per questo lo script preme il pulsante solo se il robot è in base e se l'attributo washing (o drying) non è già vero. Altrimenti risponde «già in corso» oppure «il robot non è nella base».
- if: "{{ state_attr('vacuum.robot', 'washing') == true }}"
then:
- action: script.whatsapp_rispondi
data:
chat: "{{ chat }}"
testo: "🧽 Lavaggio del panno già in corso"
- stop: Già in corso
- if: "{{ not is_state('vacuum.robot', 'docked') }}"
then:
- action: script.whatsapp_rispondi
data:
chat: "{{ chat }}"
testo: "🏠 Il robot non è nella base"
- stop: Non in base
- action: button.press
target:
entity_id: button.robot_self_clean
script.whatsapp_rispondi sta per lo script con cui rispondi già a una chat.
🔧 Manutenzione e reset dei consumabili
«Robot manutenzione» risponde con lo stato di ogni consumabile: spazzola principale, spazzola laterale, filtro, sensori, panno e detergente. Per ognuno legge dai sensori dell'integrazione la percentuale e le ore residue, e mette un semaforo: 🟢 sopra il 25%, 🟡 sotto il 25%, 🔴 sotto il 10%.
Esempio con valori inventati
«Robot reset» seguito dal nome della parte preme il pulsante di reset di quella parte, rilegge il sensore e mostra prima e dopo, per esempio «18% → 100%». Le parti stanno in una lista, ognuna con i suoi sinonimi, il sensore e il pulsante:
parti:
- nome: Spazzola laterale
parole: ['laterale']
sensore: sensor.robot_side_brush_left
reset: button.robot_reset_side_brush
- nome: Filtro
parole: ['filtro']
sensore: sensor.robot_filter_left
reset: button.robot_reset_filter
- nome: Spazzola principale
parole: ['spazzola', 'principale']
sensore: sensor.robot_main_brush_left
reset: button.robot_reset_main_brush
L'ordine conta: in «reset spazzola laterale» c'è anche la parola «spazzola», quindi «laterale» deve vincere. La spazzola principale si cerca per ultima. Se scrivo solo «robot reset», senza la parte, lo script chiede quale e mostra l'elenco.
📋 I comandi in una tabella
| Comando | Cosa fa | Quando funziona |
|---|---|---|
| robot pulisci | Pulizia nuova di tutta la casa; annulla un'attività interrotta | Sempre; dice se il robot è partito davvero |
| robot pulisci cucina e bagno | Pulizia nuova delle sole stanze nominate | Come sopra |
| robot riprendi | Continua l'attività in pausa | Solo se ce n'è una aperta |
| robot autopulizia (pulisci base, lava panno) | Lavaggio del panno nella stazione | Robot in base e lavaggio non già in corso |
| robot asciuga | Asciugatura del panno | Robot in base e asciugatura non già in corso |
| robot svuota | Svuotamento automatico | Robot in base |
| robot manutenzione | Percentuale, ore residue e semaforo dei consumabili | Sempre, non muove il robot |
| robot reset <parte> | Azzera il contatore della parte e mostra prima → ora | Sempre; senza la parte chiede quale |
Esempio: un reset e un lavaggio chiesto due volte
🧪 Come l'ho provato
Il riconoscimento delle frasi l'ho provato senza toccare il robot. Dentro il container ho usato jinja2 puro, caricando le variabili dal file YAML dello script, e gli ho fatto leggere 17 frasi, da «pulisci» a «reset spazzola laterale», controllando che per ognuna scegliesse il comando e la parte giusti.
Dal vivo ho provato solo i comandi che non muovono il robot, cioè «robot manutenzione» e «robot reset» senza la parte. Il testo inviato l'ho letto nella traccia dello script. I comandi che lo muovono o cambiano qualcosa sul robot li provo io, di persona.
🪤 Intoppi e lezioni
💡 Quello che ho imparato
- Avvia e riprendi sono spesso lo stesso servizio. Se voglio ripartire da zero, prima va annullata l'attività in corso. E prima di dare la colpa al robot conviene leggere il codice dell'integrazione e la storia degli attributi nel recorder.
- I pulsanti che funzionano da interruttore vanno protetti. Un controllo dello stato prima di premerli evita che il secondo comando annulli il primo.
- Le notifiche di avviso dell'integrazione non vanno chiuse da Home Assistant. Chiuderle cancella l'avviso anche sul robot, e si perde l'informazione proprio dove serve.
- Se la programmata si ferma ogni mattina per l'acqua, il problema è di manutenzione. Non di automazione: l'avviso tradotto su WhatsApp lo fa notare subito, e il serbatoio va riempito o svuotato.