This post may contain affiliate links. Please read my disclaimer for more info.

Looking to free your robot vacuum from the cloud? Want to control your vacuum over MQTT and have full access to the map it generates of your house? Today’s article will walk you through installing Valetudo. Valetudo is a binary that runs on rooted Roborock S5 vacuums that enable users to fully control the vacuum without any cloud connection whatsoever. I’ll also walk through getting the generated map displaying in your Home Assistant instance so you can monitor your vacuum as it cleans your house!

Pros and Cons

Valetudo is a service you can install on the Roborock S5 which essentially creates a server application to control the robot. You can use the web page to control the robot in the same way you may have used an app previously (and the web page is mobile friendly).

A major benefit is that the map data is available through this application, so Home Assistant (and other applications) can access it.

So what does this really get you?

You can control your vacuum over MQTT

You can control your vacuum through the web interface (on your computer or mobile device)

The vacuum no longer uploads the map data to the Xiaomi cloud. It keeps it local to the vacuum and you can access it over your network.

You can display the map (including progress while cleaning) within Home Assistant

You might have some hesitation about installing something on your robot vacuum. To answer some questions upfront:

You can easily remove this (by doing a factory reset)

You can still do zoned cleaning, spot cleaning, change fan speed, etc.. through Valetudo

You can still start, stop, check battery from the Mi Home and FloleVac apps.

You will not be able to access the map through the Mi Home and FloleVac apps. So you cannot start a zoned-clean through the apps.

You can still use the xiaomi_miio integration in Home Assistant to control the robot. You don’t have to move to MQTT. So if you used my article how to setup zoned cleaning through Home Assistant, that will continue to work.

So it’s up to you to decide if it’s worth it. Luckily, you can always just factory reset the vacuum if you don’t like using it.

Building and Installing the Image

Building and installing the image is pretty straightforward unless you want to customize a lot. The Valetudo documentation has complete instructions if you are looking to build the image from scratch and customize it. If you are okay with using a stock Valetudo release I’ll walk you through the steps I did here.

Building the Image

First off, we’ll need an ssh key so that we can later log into the vacuum. If you use git or ssh you are probably familiar with ssh and have an ssh public key sitting in your ~/.ssh/ directory.

If you don’t have an ssh key already, go ahead and generate one. These instructions from GitHub are pretty straightforward to follow.

Once you have your SSH key we can create a new Roborock image with the key set up and Valetudo preinstalled.

Go to the DustBuilder website, we’ll use this online tool to create the image for us. Upload the public piece of your ssh key (usually ending in .pub) to the website and check the boxes as seen in my screenshot below. I’ve got a Roborock S5 Gen 2 so I selected that. If you have Gen 1 make sure to make the appropriate change!

Hit submit and get some coffee or a beer and wait to get an email back with your image. While waiting, go and download RoboRock Control Center, we’ll be using it to upload the image to the vacuum.

Installing the Image

You should receive an email after a while (mine took about 10 minutes) with a few URLs to download your image. Go ahead and download the .pkg file from the link provided. You can check the hash of the image using a command-line tool like md5sum to verify it matches the checksum provided in the email.

To install the image, the easiest way is using RoboRock Control Center. On the first launch of the app, you’ll need to set the IP address and the token for the vacuum. If you don’t already have the token, take a break and refer back to my Zoned Cleaning with the Xiaomi Roborock S5 Robotic Vacuum article which discusses how to extract the token from the Mi Home app.

Once RRCC is configured, we can upload the new image. Go to the Firmware menu and click “Update”. This will launch a file browser window to allow you to choose the *.pkg file you got emailed earlier. Make sure you generated an image for the correct model of vacuum in the previous steps. Choose your image and start the update progress.

Somewhere during the update process, you’ll hear your vacuum announcing that it’s updating its firmware. Just be patient, it can take 10 minutes to download and install the firmware on the vacuum.

That’s it! Your robot now has Valetudo installed. In a web browser type in the IP address of your vacuum and you should see the Valetudo front end. You should also be able to just type http://rockrobo in your browser as well and it should redirect correctly.

At this point, you should be able to still control some functionality in the FloleVac and Mi Home Apps, but you will no longer be able to access the vacuum’s map through those apps.

Home Assistant Integration

Now that your vacuum is free from the cloud, there are a few things you can do. To enable most of this you’ll need be modifying some Valetudo configuration files that are now sitting on your vacuum. There are a few ways to do that. First off, you could ssh into the vacuum using the username “root”, since you added your public key to the vacuum while creating the image, it should log in automatically.

ssh root@192.168.1.12 1 ssh root @ 192.168.1.12

Once inside you can use a command-line program like vi or nano to edit the files needed.

Alternatively, you can mount the filesystem of the robot onto another computer using a tool called sshfs. Digital Ocean has a great tutorial to get started using sshfs.

Enabling MQTT on your Vacuum

To enable MQTT on your Vacuum you’ll need to edit the /mnt/data/valetudo/config.json file. Within that file there is a section for MQTT. Enable it and put in the broker URL and change any other settings you want, including enabling the map data. The MQTT section should end up looking something like this:

"mqtt": { "enabled": true, "identifier": "rockrobo", "topicPrefix": "valetudo", "autoconfPrefix": "homeassistant", "broker_url": "mqtt://192.168.1.2", "provideMapData": true, "caPath": "" }, 1 2 3 4 5 6 7 8 9 "mqtt" : { "enabled" : true , "identifier" : "rockrobo" , "topicPrefix" : "valetudo" , "autoconfPrefix" : "homeassistant" , "broker_url" : "mqtt://192.168.1.2" , "provideMapData" : true , "caPath" : "" } ,

After making that change, you’ll need to restart Valetudo. Simply run service valetudo restart to restart Valetudo. Your robot should now be controllable via MQTT and sending map data over MQTT.

You can still use the Xiaomi Mi Robot Vacuum integration in Home Assistant if you want. Or you can also switch over to using MQTT through Home Assistant. This requires you to add MQTT discovery to your Home Assistant MQTT integration.

mqtt: discovery: true discovery_prefix: homeassistant 1 2 3 mqtt : discovery : true discovery _ prefix : homeassistant

After restarting Home Assistant you should now have an MQTT Vacuum you can control over your local network.

Creating a Map Image

If you are a fan of the Home Assistant states view, you can use the generic IP camera integration to add the map to Home Assistant. First off, we’ll need to create the map as a png and have it update in real-time. Rather than doing this on the robot, it’s more efficient to run a service on your server or Raspberry Pi to generate the map.

There is a project called I Can’t Believe It’s Not Valetudo that takes the Valetudo MQTT data and generates a map that you can import into Home Assistant. Getting started is really easy, I added a docker container for “I Can’t Believe It’s Not Valetudo” to my docker-compose.yml file.

--- version: "3" services: icbinv: image: dmkif/icantbelieveitsnotvaletudo:latest user: 1000:1000 volumes: - ./config/icbinv/config.json:/app/config.json network_mode: "host" 1 2 3 4 5 6 7 8 9 10 11 --- version : "3" services : icbinv : image : dmkif/icantbelieveitsnotvaletudo :latest user : 1000 :1000 volumes : - . /config/icbinv/config . json :/app/config.json network _ mode : "host"

Notice that I mount in a configuration file. The contents are seen below:

{ "mqtt": { "identifier": "rockrobo", "topicPrefix": "valetudo", "autoconfPrefix": "homeassistant", "broker_url": "mqtt://192.168.1.2", "caPath": "", "mapSettings": { "drawPath": true, "drawCharger": true, "drawRobot": true, "border": 2, "scale": 4 }, "mapDataTopic": "valetudo/rockrobo/map_data", "minMillisecondsBetweenMapUpdates": 10000, "publishMapImage": true }, "webserver": { "enabled": true, "port": 3030 } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 { "mqtt" : { "identifier" : "rockrobo" , "topicPrefix" : "valetudo" , "autoconfPrefix" : "homeassistant" , "broker_url" : "mqtt://192.168.1.2" , "caPath" : "" , "mapSettings" : { "drawPath" : true , "drawCharger" : true , "drawRobot" : true , "border" : 2 , "scale" : 4 } , "mapDataTopic" : "valetudo/rockrobo/map_data" , "minMillisecondsBetweenMapUpdates" : 10000 , "publishMapImage" : true } , "webserver" : { "enabled" : true , "port" : 3030 } }

The important part here to match the broker_url with your MQTT server and set the port to whatever port you want this service to run on.

Startup the service and navigate to http://host:port/api/map/image to see the image being created.

You can then add this image as a generic IP camera in Home Assistant to have it show up as a new entity.

--- platform: generic name: Vacuum Map still_image_url: http://host:port/api/map/image content_type: image/png framerate: 1 1 2 3 4 5 6 7 --- platform : generic name : Vacuum Map still _ image _ url : http ://host :port/api/map/image content _ type : image/png framerate : 1

This results in a new camera entity showing up in your frontend.

Lovelace Card

If you’re a Lovelace user, you can skip “I Can’t Believe It’s Not Valetudo” and creating the generic camera entity. We can add a Lovelace card that generates the map itself.

To do so, you first need to create a REST sensor that will read the map data from your robot and store it as an entity.

--- platform: rest resource: http://192.168.1.12/api/map/latest name: valetudo_map json_attributes: - image - path - charger - robot value_template: 'OK' scan_interval: 5 1 2 3 4 5 6 7 8 9 10 11 12 --- platform : rest resource : http ://192.168.1.12/api/map/latest name : valetudo_map json _ attributes : - image - path - charger - robot value _ template : 'OK' scan _ interval : 5

Since this is a lot of data, I recommend excluding it from the recorder integration so you’re not storing it all in your database.

recorder: # Ignore some entities that generate lots of data and aren't useful exclude: entities: - sensor.valetudo_map 1 2 3 4 5 recorder : # Ignore some entities that generate lots of data and aren't useful exclude : entities : - sensor . valetudo _ map

Now that you have a new sensor with map data, we can plot it using the Lovelace Valetudo Map Card. Go ahead and install the card and then when you configure it, you just need to tell it what sensor has the data.

- type: "custom:valetudo-map-card" entity: sensor.valetudo_map rotate: 0 crop: top: 70 bottom: 70 left: 20 right: 20 min_height: 0 1 2 3 4 5 6 7 8 9 - type : "custom :valetudo-map-card" entity : sensor.valetudo_map rotate : 0 crop : top : 70 bottom : 70 left : 20 right : 20 min _ height : 0

Which results in a nice Lovelace card on your front end.

Creating an Nginx Proxy

If you have followed my article on Reverse Proxy with HTTPS without Opening Ports you’ll be able to add a new subdomain for accessing Valetudo. I created a new subdomain at vacuum.example.com on my network so that I could easily type in the URL anywhere and access the interface.

All it requires is creating a new subdomain configuration file for Nginx. Below is the one I used, after restarting you should be able to access the Valetudo interface.

server { listen 443 ssl; listen [::]:443 ssl; server_name vacuum.*; include /config/nginx/ssl.conf; client_max_body_size 0; # enable for ldap auth, fill in ldap details in ldap.conf #include /config/nginx/ldap.conf; location / { resolver 127.0.0.11 valid=30s; proxy_pass http://192.168.1.12:80; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 server { listen 443 ssl ; listen [ : : ] : 443 ssl ; server_name vacuum . * ; include / config / nginx / ssl . conf ; client_max_body_size 0 ; # enable for ldap auth, fill in ldap details in ldap.conf #include /config/nginx/ldap.conf; location / { resolver 127.0.0.11 valid = 30s ; proxy_pass http : //192.168.1.12:80; proxy_set_header Host $ host ; proxy_http_version 1.1 ; proxy_set_header Upgrade $ http_upgrade ; proxy_set_header Connection "upgrade" ; } }

Notice that you will have to modify the proxy_pass variable to match the IP address of your robot vacuum (which Valetudo is running on).

Adding the Valetudo Screen to Home Assistant

Finally, to access the Valetudo controls from Home Assistant you can add a new sidebar entry using the panel iframe integration. Here’s all the YAML you need to add the new iframe entry to your setup.

--- # Adds an iframe panel to the Home Assistant frontend for Valetudo. # This allows me to access Valetudo straight from Home Asssitant's UI # # https://www.home-assistant.io/components/panel_iframe/ # valetudo: title: Valetudo icon: mdi:robot-vacuum-variant url: !secret panel_iframe_valetudo_url 1 2 3 4 5 6 7 8 9 10 --- # Adds an iframe panel to the Home Assistant frontend for Valetudo. # This allows me to access Valetudo straight from Home Asssitant's UI # # https://www.home-assistant.io/components/panel_iframe/ # valetudo : title : Valetudo icon : mdi :robot-vacuum-variant url : !secret panel_iframe_valetudo_url

This results in a nice side bar item to have complete control of your vacuum.

Conclusion

I hope you enjoyed my tutorial on running Valetudo on my Roborock S5. I just touched on the basics here. There’s more configuration you can do in both Valeutdo and Home Assistant to get your map looking awesome. If you haven’t already, check out my other article on Zoned Cleaning with the Xiaomi Roborock S5 Robotic Vacuum. Hans Oischinger (@oischinger on twitter) also linked me to his cool article on integrating zoned cleanup with the live map if you need some further inspiration.

If you found this tutorial helpful, please consider supporting the blog by joining my mailing list, following the blog on social media or directly through Buy Me a Coffee. Thanks for reading!