{"id":5210,"date":"2026-08-24T09:58:00","date_gmt":"2026-08-24T14:58:00","guid":{"rendered":"https:\/\/lab.rapternet.us\/?p=5210"},"modified":"2026-08-17T21:14:26","modified_gmt":"2026-08-18T02:14:26","slug":"installing-valetudo-on-a-dreame-x40-ultra","status":"publish","type":"post","link":"https:\/\/lab.rapternet.us\/?p=5210","title":{"rendered":"Installing Valetudo on a Dreame X40 Ultra"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I picked up a Dreame X40 Ultra with the intent of installing Valetudo on it. Valetudo is an open source project that cuts the vacuums ties to the cloud and allows it to run entirely locally. This means the map of your house remains your own, the camera feeds from the vacuum remain yours, and all other sensor data remains local and isn&#8217;t sold to the nearest bidder.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">A Word of Caution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This shouldn&#8217;t be treated as a guide to the whole process, use the <a href=\"https:\/\/valetudo.cloud\/pages\/installation\/dreame\/#fastboot\">official valetudo guides <\/a>for that. This is just a bit of my experience in the process of rooting and flashing valetudo onto a robot vacuum.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Onwards<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The X40 Ultra needs to be rooted before Valetudo can be installed on it. To make this easier, the project has the designs for a breakout board to connect the vacuum to your PC before running the commands on it to run the install. I received my board from a community member who had just flashed two vacuums for their own use.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679-1024x769.jpg\" alt=\"\" class=\"wp-image-5231\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260701_190113251395347604911922679.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Dreame breakout PCB<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To get to the connector on the vacuum, you have to pop off the front top plate. It&#8217;s just clipped into place, no screws needed. The port is near the lidar sensor.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294-1024x769.jpg\" alt=\"\" class=\"wp-image-5230\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294-1024x769.jpg 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294-300x225.jpg 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294-768x577.jpg 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294-1536x1154.jpg 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/pxl_20260706_2324135398010272006592728294.jpg 2000w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><figcaption class=\"wp-element-caption\">Dreame breakout PCB installed in the debug header<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The guides on valetudos site are great. I followed the <a href=\"https:\/\/valetudo.cloud\/pages\/installation\/dreame\/#fastboot\" target=\"_blank\" rel=\"noreferrer noopener\">dreame fastboot guide<\/a> there for my flashing process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Linux Setup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To start out with, I needed to install Linux on my extra mini PC (only extra PC I have). If I had used a laptop, it would&#8217;ve been easier (built in WiFi is needed for part of the process). I installed Debian 13 with a KDE desktop environment.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With that done, I had to install two tools:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>sunxi-tools<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>fastboot<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">That is all that&#8217;s needed for Linux tooling for flashing. I needed a <a href=\"https:\/\/lab.rapternet.us\/?p=5208\">USB Wi-Fi adapter as well and the driver <\/a>for it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Into FastBoot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll need to get into fastboot multiple times through the process of rooting and flashing valetudo to the robot vacuum. Once in fastboot, we have 160 seconds to perform our actions before the watchdog reboots the system. We don&#8217;t have to worry about that timer too much for the first phase of information gathering, but once we get to rooting, we need to finish it within the timeframe or risk bricking the vacuum.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below is the output from the terminal commands I ran to get into fastboot. I kept getting warnings that there was no soc_sram_info, but thats nothing to worry about.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">root@dreamroot:\/home\/stephen\/Downloads# sunxi-fel ver<br>Warning: no 'soc_sram_info' data for your SoC (id=1855)<br>AWUSBFEX soc=00001855(unknown) 00000001 ver=0001 44 08 scratchpad=00042200 00000000 00000000<br><br>root@dreamroot:\/home\/stephen\/Downloads# sunxi-fel write 0x28000 fsbl_ddr4.bin<br>Warning: no 'soc_sram_info' data for your SoC (id=1855)<br>root@dreamroot:\/home\/stephen\/Downloads# sunxi-fel exe 0x28000<br>Warning: no 'soc_sram_info' data for your SoC (id=1855)<br>root@dreamroot:\/home\/stephen\/Downloads# sleep 5<br><br>root@dreamroot:\/home\/stephen\/Downloads# sunxi-fel write 0x4a000000 payload.bin<br>sunxi-fel exe 0x4a000000<br>Warning: no 'soc_sram_info' data for your SoC (id=1855)<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Phase 1: Recon<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I moved slowly during the phase 1 of the process. I wanted to make sure I knew what was going on. In doing so, I did end up running out the timer and had to get back into fastboot to finish the recon process.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stephen@dreamroot:~$ fastboot devices<br>Android Fastboot         Android Fastboot<br><br>stephen@dreamroot:~$ fastboot getvar dustversion<br>dustversion: 2024.12.00<br>Finished. Total time: 0.003s<br>stephen@dreamroot:~$ fastboot getvar config<br>config: 6f5902ac237024bdd0c176cb93063dc4<br>Finished. Total time: 0.226s<br>stephen@dreamroot:~$ fastboot get_staged dustx100.bin<br>Uploading 'dustx100.bin'                           OKAY [ 37.629s]<br>Finished. Total time: 37.629s<br><br>stephen@dreamroot:~$ du -h dustx100.bin<br>400M    dustx100.bin<br>stephen@dreamroot:~$ fastboot oem stage1<br>OKAY [  0.000s]<br>Finished. Total time: 0.000s<br>stephen@dreamroot:~$ fastboot get_staged dustx101.bin<br>Uploading 'dustx101.bin'                           FAILED (Read from device failed in ReadBuffer() (Protocol error))<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The protocol error was the sign that I had overran my time limit and needed to get back into fastboot. After getting back into fastboot I finished up the recon phase:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stephen@dreamroot:~$ fastboot get_staged dustx101.bin<br>&lt; waiting for any device &gt;<br>Uploading 'dustx101.bin'                           OKAY [ 37.528s]<br>Finished. Total time: 37.528s<br>stephen@dreamroot:~$ du -h dustx101.bin<br>399M    dustx101.bin<br><br>stephen@dreamroot:~$ fastboot getvar config<br>config: d822d7fdcfb675425e2faf9f14309818<br>Finished. Total time: 0.225s<br>stephen@dreamroot:~$ fastboot oem stage2<br>OKAY [  0.000s]<br>Finished. Total time: 0.000s<br>stephen@dreamroot:~$ fastboot get_staged dustx102.bin<br>Uploading 'dustx102.bin'                           OKAY [ 37.366s]<br>Finished. Total time: 37.366s<br>stephen@dreamroot:~$ du -h dustx102.bin<br>399M    dustx102.bin<br>stephen@dreamroot:~$ zip dreame_rxxxx_samples.zip dustx100.bin dustx101.bin dustx102.bin<br>  adding: dustx100.bin (deflated 0%)<br>  adding: dustx101.bin (deflated 0%)<br>  adding: dustx102.bin (deflated 0%)<br>stephen@dreamroot:~$ du -h dreame_rxxxx_samples.zip<br>1.2G    dreame_rxxxx_samples.zip<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Dustbuilder<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I had to then take all the info to upload to dustbuilder and wait for the system to build the images I needed to flash the vacuum with. This was a fairly straightforward process. Once I had everything downloaded to my Linux machine, I was ready for the final flashing.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Job scheduled on the blockchain as j6a4c389e19cb3 (77e219808a87c55b2c0ae0d34f337203).<br>Check your email! If you dont get a Mail in the next few minutes, your Email provider might have blocked it.<br>According to your serial number, the root password to your vacuum should be \"ZGU5NWU2ZTkwODU0Y2VmM2NiMzUzYTRkMmJhNGFkNDIgIC0K\"<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Phase 2: Rooting<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In order to avoid running into the timeout again. So this time I prepped all of the commands in a text file prior to running it all. The following segment was getting into fastboot.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sunxi-fel write 0x28000 fsbl.bin<br>sunxi-fel exe 0x28000<br>sleep 5<br>sunxi-fel write 0x4a000000 payload.bin<br>sunxi-fel exe 0x4a000000<br>fastboot devices<br>fastboot getvar config<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is the timed portion that matters, there is 160 seconds to complete this process, else there is a chance of permanently bricking the robot vacuum. Similarly to the last step, I&#8217;ve prepped all the commands ahead of running them all.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">fastboot oem dust 118e6b3b<br>fastboot oem prep<br>fastboot flash toc1 toc1.img<br>fastboot flash boot1 boot.img<br>fastboot flash rootfs1 rootfs.img<br>fastboot flash boot2 boot.img<br>fastboot flash rootfs2 rootfs.img<br><br><br>fastboot reboot<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Below is the full log of that finial bit of the configuration. Every command I ran returned the OKAY status. <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot devices<br>Android Fastboot\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Android Fastboot<br><br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot getvar config<br>config: 6f5902ac237024bdd0c176cb93063dc4<br>Finished. Total time: 0.209s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot oem dust 118e6b3b<br>OKAY [\u00a0 0.000s]<br>Finished. Total time: 0.000s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot oem prep<br>OKAY [\u00a0 0.005s]<br>Finished. Total time: 0.005s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot flash toc1 toc1.img<br>Warning: skip copying toc1 image avb footer (toc1 partition size: 0, toc1 image size: 1245184).<br>Sending 'toc1' (1216 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.063s]<br>Writing 'toc1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.045s]<br>Finished. Total time: 0.118s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot flash boot1 boot.img<br>Warning: skip copying boot1 image avb footer (boot1 partition size: 0, boot1 image size: 13647872).<br>Sending 'boot1' (13328 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.717s]<br>Writing 'boot1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.245s]<br>Finished. Total time: 0.973s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot flash rootfs1 rootfs.img<br>Warning: skip copying rootfs1 image avb footer (rootfs1 partition size: 0, rootfs1 image size: 140724461119920).<br>Sending sparse 'rootfs1' 1\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.726s]<br>Writing 'rootfs1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.675s]<br>Sending sparse 'rootfs1' 2\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.790s]<br>Writing 'rootfs1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.701s]<br>Sending sparse 'rootfs1' 3\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.759s]<br>Writing 'rootfs1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.678s]<br>Sending sparse 'rootfs1' 4\/4 (29136 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.544s]<br>Writing 'rootfs1'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.748s]<br>Finished. Total time: 9.702s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot flash boot2 boot.img<br>Warning: skip copying boot2 image avb footer (boot2 partition size: 0, boot2 image size: 13647872).<br>Sending 'boot2' (13328 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.719s]<br>Writing 'boot2'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.247s]<br>Finished. Total time: 0.976s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot flash rootfs2 rootfs.img<br>Warning: skip copying rootfs2 image avb footer (rootfs2 partition size: 0, rootfs2 image size: 140721905908160).<br>Sending sparse 'rootfs2' 1\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.698s]<br>Writing 'rootfs2'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.704s]<br>Sending sparse 'rootfs2' 2\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.730s]<br>Writing 'rootfs2'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.683s]<br>Sending sparse 'rootfs2' 3\/4 (32764 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.743s]<br>Writing 'rootfs2'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.682s]<br>Sending sparse 'rootfs2' 4\/4 (29136 KB)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 1.531s]<br>Writing 'rootfs2'\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.765s]<br>Finished. Total time: 9.617s<br>stephen@dreamroot:~\/Downloads\/Valetudo\/fel$ fastboot reboot<br>Rebooting\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OKAY [\u00a0 0.000s]<br>Finished. Total time: 1.510s<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Backing up Data Prior to Valetudo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">It was time to backup a few folders from the vacuum and upload them to my Linux machine just in case. I had to try a few attempts at the curl command to post the TAR file up to my machine, but it wasn&#8217;t too hard to get the command right (my file ended up in \/tmp rather than the local folder from the example). <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stephen@dreamroot:~$ ssh -i .ssh\/id_rsa\u00a0 root@192.168.5.1<br>The authenticity of host '192.168.5.1 (192.168.5.1)' can't be established.<br>ED25519 key fingerprint is SHA256:fPq9GCUAASf70gl1BwRPpxQRLu07neiM2+hO87EzgHI.<br>This key is not known by any other names.<br>Are you sure you want to continue connecting (yes\/no\/[fingerprint])? yes<br>Warning: Permanently added '192.168.5.1' (ED25519) to the list of known hosts.<br>--------------------------------------------------------------<br>\u00a0\u00a0\u00a0 _\u00a0\u00a0 _\u00a0\u00a0 _\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 _\u00a0\u00a0\u00a0\u00a0 _<br>\u00a0\u00a0 \/ \\ | |_| |__\u00a0\u00a0 ___ _ __\u00a0\u00a0 __ _\u00a0 | |\u00a0\u00a0 (_)_ __\u00a0 _\u00a0\u00a0 ___\u00a0 __<br>\u00a0 \/ _ \\| __| '_ \\ \/ _ \\ '_ \\ \/ _` | | |\u00a0\u00a0 | | '_ \\| | | \\ \\\/ \/<br> \/ ___ \\ |_| | | |\u00a0 __\/ | | | (_| | | |___| | | | | |_| |>\u00a0 &lt;<br>\/_\/\u00a0\u00a0 \\_\\__|_| |_|\\___|_| |_|\\__,_| |_____|_|_| |_|\\__,_\/_\/\\_\\<br><br>--------------------------------------------------------------<br> Athena Linux (r2416_release)<br>--------------------------------------------------------------<br><br>built with dustbuilder (https:\/\/builder.dontvacuum.me)<br>2026-07-06T23:25:07Z<br>1760<br>[root@r2416_release:~]# tar cvf \/tmp\/backup.tar \/mnt\/private\/ \/mnt\/misc\/<br>tar: removing leading '\/' from member names<br>mnt\/private\/<br>mnt\/private\/ULI\/<br>mnt\/private\/ULI\/factory\/<br>mnt\/private\/ULI\/factory\/key.txt<br>mnt\/private\/ULI\/factory\/sn.txt<br>mnt\/private\/ULI\/factory\/did.txt<br>mnt\/private\/ULI\/factory\/mac.txt<br>mnt\/private\/ULI\/factory\/timezone.txt<br>mnt\/private\/ULI\/factory\/language.txt<br>mnt\/private\/ULI\/factory\/nation.txt<br>mnt\/private\/ULI\/factory\/cpuid.txt<br>mnt\/misc\/<br>mnt\/misc\/private.tar.gz<br>mnt\/misc\/totalruntime<br>mnt\/misc\/lost+found\/<br>mnt\/misc\/consumable.json<br>mnt\/misc\/lds_name<br>mnt\/misc\/authorized_keys<br>mnt\/misc\/caliberation_result.json<br>mnt\/misc\/rgb_extrinsic.json<br>mnt\/misc\/lds_config.json<br>mnt\/misc\/rgb_intrinsic.json<br>mnt\/misc\/unical-config.jsonc<br>mnt\/misc\/dm<br>mnt\/misc\/tee\/<br>mnt\/misc\/tee\/1<br>mnt\/misc\/tee\/0<br>mnt\/misc\/tee\/2<br>mnt\/misc\/tee\/dirf.db<br>mnt\/misc\/unical-robot.jsonc<br><br>[root@r2416_release:~]# curl -X POST http:\/\/192.168.5.100:1337\/upload -F 'file=@\/tmp\/backup.tar'<br>Successfully uploaded file to \"\/home\/stephen\/Downloads\/www\/uploads\/backup.tar\"<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once it was all backed up, it was time to get valetudo off the machine and onto the vacuum and install it all.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[root@r2416_release:~]# wget http:\/\/192.168.5.101:1337\/valetudo<br>--1970-01-01 08:07:51--\u00a0 http:\/\/192.168.5.101:1337\/valetudo<br>Connecting to 192.168.5.101:1337... ^C<br>[root@r2416_release:~]# wget http:\/\/192.168.5.100:1337\/valetudo<br>--1970-01-01 08:07:57--\u00a0 http:\/\/192.168.5.100:1337\/valetudo<br>Connecting to 192.168.5.100:1337... connected.<br>HTTP request sent, awaiting response... 200 OK<br>Length: 38763397 (37M) [application\/octet-stream]<br>Saving to: 'valetudo'<br><br>valetudo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 100%[=========================================================>]\u00a0 36.97M\u00a0 4.79MB\/s\u00a0\u00a0\u00a0 in 11s<br><br>1970-01-01 08:08:08 (3.44 MB\/s) - 'valetudo' saved [38763397\/38763397]<br><br>[root@r2416_release:~]# mv \/tmp\/valetudo \/data\/valetudo<br>[root@r2416_release:~]# chmod +x \/data\/valetudo<br>[root@r2416_release:~]# cp \/misc\/_root_postboot.sh.tpl \/data\/_root_postboot.sh<br>[root@r2416_release:~]# chmod +x \/data\/_root_postboot.sh<br>[root@r2416_release:~]#<br>[root@r2416_release:~]# reboot<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Changing the DID<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The only hiccup I ran into was one that the valetudo guide also mentions so I was prepared to fix it. My vacuum came with a negative Device ID value, which is invalid for valetudo. Fixing it is as simple as editing the did.txt file and changing the value to a positive number, removing the device.conf, and telling the vacuum to reboot (where it will generate a new device.conf and everything will just work). Honestly dirt easy to fix.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">stephen@dreamroot:~$ ssh -i .ssh\/id_rsa  root@192.168.5.1<br>--------------------------------------------------------------<br>    _   _   _                        _     _<br>   \/ \\ | |_| |__   ___ _ __   __ _  | |   (_)_ __  _   ___  __<br>  \/ _ \\| __| '_ \\ \/ _ \\ '_ \\ \/ _` | | |   | | '_ \\| | | \\ \\\/ \/<br> \/ ___ \\ |_| | | |  __\/ | | | (_| | | |___| | | | | |_| |&gt;  &lt;<br>\/_\/   \\_\\__|_| |_|\\___|_| |_|\\__,_| |_____|_|_| |_|\\__,_\/_\/\\_\\<br><br>--------------------------------------------------------------<br> Athena Linux (r2416_release)<br>--------------------------------------------------------------<br><br>built with dustbuilder (https:\/\/builder.dontvacuum.me)<br>[root@r2416_release:~]# cat \/mnt\/private\/ULI\/factory\/did.txt<br>[root@r2416_release:~]# cp \/mnt\/private\/ULI\/factory\/did.txt \/mnt\/private\/ULI\/factory\/did_orig.txt &amp;&amp; sync<br>[root@r2416_release:~]# nano \/mnt\/private\/ULI\/factory\/did.txt<br>[root@r2416_release:~]# rm \/data\/config\/miio\/device.conf<br>[root@r2416_release:~]# reboot<br><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Valetudo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The web interface is straight forward and easy to get started in. you can pick vacuum\/mop modes, configure the vacuums configuration settings, turn up or down the fan speeds, check on dock statistics, and more. Everything that the cloud gave you, can be done entirely locally, which is refreshing for devices like this (and only comes from the open source community doing projects like this to ensure devices are owned by the users).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"582\" height=\"929\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-5.png\" alt=\"\" class=\"wp-image-5283\" style=\"width:582px;height:auto\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-5.png 582w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-5-188x300.png 188w\" sizes=\"auto, (max-width: 582px) 100vw, 582px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Zooming in on the map I can even see what the camera detected obstacles as, whether its chair legs, wires, or other objects. It does a good job at avoiding them. There&#8217;s also a configuration option to take pictures of all the obstacles, but I haven&#8217;t used that option.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"670\" height=\"674\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-6.png\" alt=\"\" class=\"wp-image-5284\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-6.png 670w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-6-298x300.png 298w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-6-150x150.png 150w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-6-100x100.png 100w\" sizes=\"auto, (max-width: 670px) 100vw, 670px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Statistics \/ Achievements<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Valetudo also has achievements built into it for various aspects of running the vacuum. There are achievements for the number of times run, number of running hours, and area covered. They&#8217;re not really necessary, but fun to have.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"511\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-3-1024x511.png\" alt=\"\" class=\"wp-image-5281\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-3-1024x511.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-3-300x150.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-3-768x383.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-3.png 1174w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Robot Options<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The robot options page lets you fine tune options for object detection, motion, do not disturb times, various options for how to handle carpeting vs hard flooring, and more. I left this for the most part on the stock settings, and they are pretty good. I may tune them in the future. The only setting I setup an automation for right away was to mute the speaker at night (oddly that is not what the do not disturb mode does).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"643\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-4-1024x643.png\" alt=\"\" class=\"wp-image-5282\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-4-1024x643.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-4-300x188.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-4-768x482.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-4.png 1265w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Connectivity<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For connectivity back to home assistant, we have the MQTT connection. We can also use NTP servers to get time onto the vacuum for built in schedules and other actions. Those are the main connectivity settings that I have made use of.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"489\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-7-1024x489.png\" alt=\"\" class=\"wp-image-5286\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-7-1024x489.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-7-300x143.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-7-768x367.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-7.png 1224w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Finally<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;m very happy with the new vacuum, and especially happy that its fully locally controlled. I was always hesitant to get the fancier models due to the camera feeds going to the <a href=\"https:\/\/www.technologyreview.com\/2022\/12\/19\/1065306\/roomba-irobot-robot-vacuums-artificial-intelligence-training-data-privacy\/\">unknown corporate monoliths<\/a>, but having all the data stay on my network, in my device, keeps me from being worried about the <a href=\"https:\/\/www.abc.net.au\/news\/2024-10-11\/robot-vacuum-yells-racial-slurs-at-family-after-being-hacked\/104445408\">next <\/a><a href=\"https:\/\/www.theguardian.com\/lifeandstyle\/2026\/feb\/24\/accidental-hacker-how-one-man-gained-control-robots-\">hack<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"815\" src=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21-1024x815.png\" alt=\"\" class=\"wp-image-5354\" srcset=\"https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21-1024x815.png 1024w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21-300x239.png 300w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21-768x611.png 768w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21-1536x1222.png 1536w, https:\/\/lab.rapternet.us\/wp-content\/uploads\/2026\/08\/image-21.png 1924w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>I picked up a Dreame X40 Ultra with the intent of installing Valetudo on it. Valetudo is an open source project that cuts the vacuums ties to the cloud and allows it to run entirely locally. This means the map of your house remains your own, the camera feeds from the vacuum remain yours, and &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/lab.rapternet.us\/?p=5210\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Installing Valetudo on a Dreame X40 Ultra&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":5354,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[39,49,116],"class_list":["post-5210","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","tag-home-assistant","tag-smart-home","tag-valetudo"],"_links":{"self":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/5210","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5210"}],"version-history":[{"count":17,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/5210\/revisions"}],"predecessor-version":[{"id":5357,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/posts\/5210\/revisions\/5357"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=\/wp\/v2\/media\/5354"}],"wp:attachment":[{"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lab.rapternet.us\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}