<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dreame on Nelson Chen's Blog</title><link>https://mindflakes.com/tags/dreame/</link><description>Recent content in Dreame on Nelson Chen's Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>Copyright Nelson Chen</copyright><lastBuildDate>Sun, 08 Nov 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mindflakes.com/tags/dreame/index.xml" rel="self" type="application/rss+xml"/><item><title>A wet/dry vacuum solved my Dreame L50 Ultra's hairball problem</title><link>https://mindflakes.com/posts/2026/11/08/dreame-shop-vac-adapter/</link><pubDate>Sun, 08 Nov 2026 00:00:00 +0000</pubDate><guid>https://mindflakes.com/posts/2026/11/08/dreame-shop-vac-adapter/</guid><description>&lt;p&gt;My &lt;a href="https://link.amazon/B028SS9YH"&gt;Dreame L50 Ultra&lt;/a&gt; (affiliate link) could pick up dog hair, but its dock struggled to get the dense wads of hair out of the robot and into the bag. I made an adapter so an external wet/dry vacuum could do the emptying instead, with Home Assistant handling the switching. The project is finished and in use, and I haven&amp;rsquo;t had a hairball since!&lt;/p&gt;
&lt;p&gt;I directed the project and supplied the measurements and physical fit-test feedback. Codex did the CAD implementation and Home Assistant automation work, and helped draft this post. The printed parts and physical tests were my side of the collaboration.&lt;/p&gt;
&lt;p&gt;The replacement bags annoyed me too. &lt;a href="https://link.amazon/B03Y4rZ02"&gt;Bags like these on Amazon&lt;/a&gt; (affiliate link) were about fifty cents to a dollar each. Getting them cheaper on AliExpress is an option, but it still sucks when a hairball gets stuck and the bag is only half full. Throwing away a half-full disposable bag means more waste going to landfill, on top of paying for capacity I wasn&amp;rsquo;t getting to use. Cheaper bags wouldn&amp;rsquo;t fix the dock&amp;rsquo;s inability to get the hair into them.&lt;/p&gt;
&lt;p&gt;I also looked at &lt;a href="https://makerworld.com/en/models/1624511-mova-dreame-reusable-dust-bin-no-filters-needed#profileId-1715080"&gt;this reusable dust-bin design on MakerWorld&lt;/a&gt;. I didn&amp;rsquo;t think it would be enough for my setup: the bins were small, and replacing the bag with a rigid container wouldn&amp;rsquo;t address the hairballs clogging the evacuation path. The design also calls for cutting up a vacuum bag and using its filter material in the printed bin, so it still means sacrificing a bag for filtration.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://mindflakes.com/images/dreame-shop-vac-printed-adapters.webp"&gt;&lt;img src="https://mindflakes.com/images/dreame-shop-vac-printed-adapters.webp"
alt="Two green 3D-printed parts, a flat dock adapter with a curved outlet and a separate hose elbow, beside the vacuum hardware."&gt;&lt;/a&gt;&lt;figcaption&gt;
&lt;p&gt;The printed dock adapter and separate elbow. The CAD versions for both wet/dry vacuums are shown below.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We had two wet/dry vacuums available: a &lt;strong&gt;Stanley SL18129&lt;/strong&gt; and a &lt;a href="https://link.amazon/B01E7xj0y"&gt;DeWalt DXV05P-QT&lt;/a&gt; (affiliate link). Their hoses have different connectors, so Codex made a version for each. The quieter DeWalt is the one I use now. The &lt;a href="https://github.com/nelsonjchen/wet-dry-vac-to-dreame-l50-ultra-adapter"&gt;project repository&lt;/a&gt; has the editable build123d source and downloadable STL and STEP models.&lt;/p&gt;
&lt;h2 id="keeping-the-dock-intact"&gt;Keeping the dock intact&lt;/h2&gt;
&lt;p&gt;The robot and dock stay intact. The robot empties through the dock&amp;rsquo;s existing evacuation path, then a printed adapter routes that path into a short hose connected to the wet/dry vacuum. I wanted a removable part at the bag interface, rather than cutting a hole in the dock and discovering afterward that I&amp;rsquo;d misunderstood the airflow.&lt;/p&gt;
&lt;p&gt;The design involved more than making two holes line up. The dock detects whether a bag is present, and the adapter had to sit properly in its slot, keep a seal, leave room for the hose, and remain removable. The robot&amp;rsquo;s small bin, flaps and seals also mattered when considering the external vacuum&amp;rsquo;s suction.&lt;/p&gt;
&lt;p&gt;The MakerWorld bin was useful as a starting reference, though. We took measurements of its inlet hole and mating interface, recreated that geometry in &lt;a href="https://build123d.readthedocs.io/en/latest/"&gt;build123d&lt;/a&gt;, then fine-tuned my adapter through measurements and fit tests to meet my needs. That gave us somewhere to start with the dock connection; the hose routing and vacuum-specific connectors grew from there.&lt;/p&gt;
&lt;p&gt;Codex did the parametric CAD implementation. The editable model records the dimensions and clearances, so changing a hose measurement doesn&amp;rsquo;t mean starting the whole part over. I could print small fit-test pieces before committing to a larger adapter with an elbow attached.&lt;/p&gt;
&lt;h2 id="two-vacuums-two-versions"&gt;Two vacuums, two versions&lt;/h2&gt;
&lt;p&gt;The dock interface is shared, but the hose side changes. Each version has two pieces: the card adapter that slides into the dock&amp;rsquo;s bag slot, with its first bend, and a separate plug-in 90-degree elbow to turn the hose connection downward. Making the second bend removable let us change that routing without reprinting the whole card adapter.&lt;/p&gt;
&lt;p&gt;The Stanley version started from a roughly 30.75 mm hose connector. A separate tapered socket coupon fitted that connector well. The first dock card could wiggle out; later revisions changed the trailing outline, and the third version fitted much better. Those small test pieces answered fit questions before I committed to larger prints.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://mindflakes.com/images/dreame-stanley-adapter-render.webp"&gt;&lt;img src="https://mindflakes.com/images/dreame-stanley-adapter-render.webp"
alt="CAD render of the Stanley SL18129 version: a green dock card adapter on the left and its separate plug-in elbow on the right."&gt;&lt;/a&gt;&lt;figcaption&gt;
&lt;p&gt;Stanley SL18129: the REV 5 dock adapter and matching Stanley-to-Stanley elbow, rendered from the actual CAD meshes. The pieces are separated for visibility.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I switched from the Stanley to the newer DeWalt because it was quieter. That meant measuring a different hose connector and making another version of the adapter. Its cuff measured 44.77 mm at the tip and 45.77 mm at the wider end over 62.24 mm. Codex used that taper for the portion inserted into the socket, with clearance added explicitly, and enlarged the bend for the bigger connector. A nominal hose size wasn&amp;rsquo;t enough to design the actual mating surface.&lt;/p&gt;
&lt;figure&gt;&lt;a href="https://mindflakes.com/images/dreame-dewalt-adapter-render.webp"&gt;&lt;img src="https://mindflakes.com/images/dreame-dewalt-adapter-render.webp"
alt="CAD render of the DeWalt DXV05P-QT version: a yellow dock card adapter with a larger outlet on the left and its matching separate elbow on the right."&gt;&lt;/a&gt;&lt;figcaption&gt;
&lt;p&gt;DeWalt DXV05P-QT: the measured-cuff REV 5 adapter and matching DeWalt-to-DeWalt elbow. These are CAD renders, not photos of printed parts.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There is also a Stanley-to-DeWalt elbow in the source. Having both vacuums meant this became a small family of related models, rather than one fixed hose size. The CAD checks confirm valid solids and clearance between the matching parts, and the finished DeWalt setup is now doing the job in practice.&lt;/p&gt;
&lt;h2 id="switching-the-motor-with-home-assistant"&gt;Switching the motor with Home Assistant&lt;/h2&gt;
&lt;p&gt;The smart plug is a &lt;strong&gt;Sonoff S31 running ESPHome&lt;/strong&gt;, repurposed from another job. Codex configured it and the Home Assistant automation to switch the wet/dry vacuum around the Dreame&amp;rsquo;s auto-empty cycle. The S31 exposes power measurements as well as relay control.&lt;/p&gt;
&lt;p&gt;An early end-to-end test confirmed the robot could clean, return, report its emptying state, and produce the expected relay on/off sequence. The relay stayed on for about 46 seconds in that test. That was an early check of the automation and switch states, before testing the complete airflow path.&lt;/p&gt;
&lt;p&gt;This uses the &lt;a href="https://mindflakes.com/posts/2026/11/08/dreame-l50-home-assistant/"&gt;Dreame Home Assistant integration I worked on&lt;/a&gt; to follow the robot&amp;rsquo;s status.&lt;/p&gt;
&lt;p&gt;The timing changed during development. The configuration follows the dedicated auto-empty status: wait six seconds after it becomes active, check that it&amp;rsquo;s still active, then turn the relay on. When emptying becomes idle, turn it off.&lt;/p&gt;
&lt;p&gt;The two-minute cutoff runs in ESPHome on the S31 itself. If Home Assistant or Wi-Fi drops out, the plug can still turn the vacuum off locally. It also boots with its relay off, so a reboot won&amp;rsquo;t restart the motor. Those behaviors live on the switch, alongside the normal Home Assistant control.&lt;/p&gt;
&lt;p&gt;Only after starting this project did I learn that people also use wet/dry vacuums with relays for trapping rats! I came across &lt;a href="https://www.youtube.com/watch?v=X_Pu43jwWS8"&gt;Shawn Woods testing a vacuum rat trap&lt;/a&gt;. That was a use for this combination I hadn&amp;rsquo;t expected. It wasn&amp;rsquo;t where my idea came from, but it was interesting to discover another application for switching a vacuum on in response to a trigger.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m happy with how this turned out. The adapter handles the airflow path, Home Assistant handles the motor timing, and I haven&amp;rsquo;t had a hairball since putting it into use. The quieter DeWalt also made it easier to live with. This solved the annoyance I set out to fix.&lt;/p&gt;
&lt;p&gt;If you have a similar problem, the &lt;a href="https://github.com/nelsonjchen/wet-dry-vac-to-dreame-l50-ultra-adapter"&gt;source and model files&lt;/a&gt; should give you a starting point. The useful part of keeping it parametric is that a different hose can become another variant, using its actual measurements.&lt;/p&gt;
&lt;h2 id="known-issue-the-bag-change-reminder"&gt;Known issue: the bag-change reminder&lt;/h2&gt;
&lt;p&gt;The Dreame still periodically refuses to auto-empty and tells me to change the bag. Its bag-change reminder is based on an interval, rather than a sensor measuring how full the bag actually is. That&amp;rsquo;s separate from checking whether a bag is present in the dock.&lt;/p&gt;
&lt;p&gt;With this setup, I disregard the bag-change message itself: there isn&amp;rsquo;t a dock bag to replace. The reminder can still interrupt auto-emptying, but it doesn&amp;rsquo;t mean a bag has filled up or that the adapter has developed another hairball.&lt;/p&gt;</description></item><item><title>Fixing the Home Assistant integration for my Dreame L50 Ultra</title><link>https://mindflakes.com/posts/2026/11/08/dreame-l50-home-assistant/</link><pubDate>Sun, 08 Nov 2026 00:00:00 +0000</pubDate><guid>https://mindflakes.com/posts/2026/11/08/dreame-l50-home-assistant/</guid><description>&lt;p&gt;I wanted my Dreame L50 Ultra in Home Assistant, with its settings and room controls available for my own automations. That led to a small maintenance fork, an investigation into what the phone app sends, and a surprisingly consequential missing &lt;code&gt;@property&lt;/code&gt; decorator.&lt;/p&gt;
&lt;p&gt;I directed the work, with Codex doing the investigation, code changes and regression tests. It also helped draft this post. My role was setting the goals and providing the context from my vacuum and Home Assistant setup. The work described here was done in September.&lt;/p&gt;
&lt;p&gt;The starting point was &lt;a href="https://github.com/Tasshack/dreame-vacuum"&gt;Tasshack&amp;rsquo;s Dreame integration&lt;/a&gt;. It already does the substantial work: connecting to the vacuum, exposing its settings, handling maps, and providing room-cleaning controls. &lt;a href="https://github.com/nelsonjchen/dreame-vacuum"&gt;My fork&lt;/a&gt; builds on its development branch, starting at &lt;code&gt;v2.0.0b25&lt;/code&gt;, and maintains the changes on &lt;code&gt;main&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="cleaning-up-after-failed-setup"&gt;Cleaning up after failed setup&lt;/h2&gt;
&lt;p&gt;A failed setup attempt can still have created connections, background workers, listeners, and timers. Home Assistant may try again, so those resources need to be cleaned up before another attempt adds more.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/Tasshack/dreame-vacuum/pull/1774"&gt;BigKelLearns&amp;rsquo; cleanup pull request&lt;/a&gt; and the associated &lt;a href="https://github.com/Tasshack/dreame-vacuum/issues/1762"&gt;upstream issue&lt;/a&gt; were useful starting points. The upstream snapshot already cleaned up ordinary update failures. Authentication failures and cancellation needed more attention.&lt;/p&gt;
&lt;p&gt;Cancellation was the tricky part. Cancelling an asynchronous task doesn&amp;rsquo;t stop work it has already started in a thread. Disconnect immediately, and that thread can still be creating the very resources you&amp;rsquo;re trying to close.&lt;/p&gt;
&lt;p&gt;Codex changed the cleanup to wait for that work before disconnecting. Failed setup and normal unload now use a shared shutdown routine, and pending callbacks are stopped from scheduling more updates afterward. Cleanup errors are logged without hiding the original setup error.&lt;/p&gt;
&lt;p&gt;The regression suite includes a hundred failed setup attempts using real worker threads and timers with mocked network responses. It checks that workers stop, sessions close, and the old objects can be collected. Selected tests also failed against the unpatched code in the ways the investigation predicted. That gave us something more concrete than a tidier-looking cleanup function.&lt;/p&gt;
&lt;h2 id="checking-what-my-l50-actually-supports"&gt;Checking what my L50 actually supports&lt;/h2&gt;
&lt;p&gt;“L50 Ultra” is the name on the box, but the integration deals with internal model identifiers and firmware capabilities. In the September investigation, account metadata identified mine as &lt;code&gt;dreame.vacuum.r9493h&lt;/code&gt;, running firmware build 6000.&lt;/p&gt;
&lt;p&gt;Codex compared the integration&amp;rsquo;s settings with the configuration and protocol mappings in that model&amp;rsquo;s Dreamehome app plugin. That covered things like wash-water temperature, silent drying, hair compression and obstacle crossing. Most of the settings checked were already supported. The shared plugin serves other models too, so a feature name appearing somewhere in its code wasn&amp;rsquo;t enough to say my vacuum supported it.&lt;/p&gt;
&lt;p&gt;There was a general metadata bug to fix as well: a device&amp;rsquo;s key index was checked against the capability table instead of the separate key table it actually indexed. Codex corrected the bounds check and added regression cases.&lt;/p&gt;
&lt;h2 id="the-missing-decorator"&gt;The missing decorator&lt;/h2&gt;
&lt;p&gt;The room-order investigation found a particularly small bug. The integration supports an older room-order format and a newer one, with existing logic to choose between them. But &lt;code&gt;cleaning_sequence_v2&lt;/code&gt; was missing its &lt;code&gt;@property&lt;/code&gt; decorator.&lt;/p&gt;
&lt;p&gt;The caller expected a boolean. Instead, it got a bound method, which evaluates as true. That forced the newer format even when the selection logic should have chosen the older one.&lt;/p&gt;
&lt;p&gt;Adding the decorator restored that logic. Tests cover the modern L50 path and the older fallbacks. This was a reproduced code defect found during the audit; I hadn&amp;rsquo;t observed it failing on the physical vacuum.&lt;/p&gt;
&lt;h2 id="a-small-maintenance-fork"&gt;A small maintenance fork&lt;/h2&gt;
&lt;p&gt;The result is a fork with a few specific defects fixed, building on the much larger integration Tasshack and its contributors made possible. The &lt;a href="https://github.com/nelsonjchen/dreame-vacuum/blob/main/docs/fork-validation.md"&gt;validation notes&lt;/a&gt; and &lt;a href="https://github.com/nelsonjchen/dreame-vacuum/blob/main/docs/l50-plugin-audit.md"&gt;L50 audit&lt;/a&gt; record the checks and the remaining hardware work.&lt;/p&gt;
&lt;p&gt;The lifecycle tests use mocked network responses, and the app comparison didn&amp;rsquo;t send cleaning commands or change device properties. Longer-term reconnect behavior and resource use during real cloud outages still need checking. The fixes have regression coverage; that isn&amp;rsquo;t the same as proving every model, firmware version and failure path on hardware.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad we could turn this investigation into fixes other people can inspect and reuse. If you&amp;rsquo;re working through similar setup failures or model-support questions, the fork and audit notes should give you somewhere to start.&lt;/p&gt;</description></item></channel></rss>