npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

homebridge-dyson-vis-nav

v1.4.0

Published

A Homebridge plugin that exposes the Dyson 360 Vis Nav robot vacuum to Apple Home as a native Matter robot vacuum cleaner, or as a HomeKit switch when Matter is off, via the Dyson AWS IoT MQTT gateway.

Readme


What you get

Your robot appears in the Home app as a genuine robot vacuum cleaner, with the controls Apple provides for that device type:

  • Start, pause, resume and stop a clean
  • Send it back to the dock
  • Choose a cleaning mode — Auto, Quick, Quiet or Max
  • Battery level, charging state and low-battery warning
  • What it is doing right now — cleaning, paused, heading for the dock, charging, docked
  • Problems, in plain language — bin full or missing, stuck, wheels jammed, sensor obscured, and more
  • Room cleaning, for the rooms you have mapped in the MyDyson app
  • Maps of your last 5 cleans in the plugin's settings — see Maps of recent cleans
  • Siri: "Hey Siri, start the vacuum", "Hey Siri, send the vacuum to its dock"

That is what you get with Matter enabled. Without it you still get a switch, a battery and a problem sensor — see Why Matter matters.

Everything runs through your own Homebridge. Nothing is sent anywhere except to Dyson, exactly as the MyDyson app does.

Before you start

| | | |---|---| | Robot | Dyson 360 Vis Nav, added to your MyDyson account | | Homebridge | 2.4.0 or newer | | Node.js | 22, 24 or 26 | | Matter | Strongly recommended, on the bridge the plugin runs on — see step 2. Without it the robot appears as a switch rather than as a robot vacuum | | Apple Home | iOS 18.4 / iPadOS 18.4 / tvOS 18.4 or newer, on every device that should control it |

Why Matter matters

Apple never added robot vacuums to HomeKit itself. It added them to the Home app through Matter, which is why this plugin asks for it.

With Matter switched off the plugin still works, but HomeKit has no robot vacuum for your robot to be, so it appears as the nearest things HomeKit does have:

  • a switch — on starts a clean, off sends the robot back to its dock
  • its battery, with charging state and low-battery warning
  • a problem sensor — a contact sensor that opens when the robot needs attention, which an automation can react to

Cleaning modes, room cleaning, and pause and resume have no HomeKit equivalent, and are left out rather than bent onto a control that would mean something else. The log says which of the two you are getting, every time the plugin starts.

Homebridge 2.0 speaks Matter alongside HomeKit, so switching it on costs you nothing: your other accessories carry on exactly as before.


Step 1 — Install the plugin

Open the Homebridge UI, go to Plugins, search for homebridge-dyson-vis-nav, and click Install.

Newly published plugins take a while to appear in the search. If it does not come up, type the full name — the Homebridge UI looks anything beginning with homebridge- up directly, bypassing the search index.

Install into the directory hb-service uses for plugins — on a standard install that is <storage path>/node_modules, with the storage path usually /var/lib/homebridge:

sudo npm --prefix /var/lib/homebridge install homebridge-dyson-vis-nav
sudo hb-service restart

hb-service add homebridge-dyson-vis-nav works too. It does not accept URLs or file paths, only names from npm.

Step 2 — Give it a child bridge with Matter

Matter has to be enabled on whichever bridge this plugin runs on. Putting the plugin in its own child bridge and enabling Matter there is the tidier way round: your main bridge keeps running exactly as it does today, and the robot stays isolated from your other accessories.

  1. In the Homebridge UI, go to Plugins and open the ⋮ menu next to Dyson 360 Vis Nav.
  2. Choose Bridge Settings, switch the child bridge on, and enable Matter for it.
  3. Save, then restart Homebridge.

You can also switch Matter on globally, under Settings → Matter, and skip the child bridge. It works the same way; it just turns Matter on for the whole instance rather than for this plugin alone.

Step 3 — Connect your MyDyson account

  1. In the Homebridge UI, open the plugin's Settings.

  2. In the MyDyson Account box at the top, enter the email address and password you use with the MyDyson app.

  3. Click Request code.

    There is nothing to do in the MyDyson app itself. Dyson sends you an email titled "Log in to your MyDyson App" containing a short code. Check your spam folder if it does not turn up within a minute.

  4. Type that code into Auth code and click Submit.

    The box collapses to ✓ Authorised once it works, and shows how many devices were found in your account.

  5. Click Save, then Restart Homebridge.

What is stored, and where

| | | |---|---| | Email address, password | Homebridge's config.json, in plain text | | Access token | the plugin's own storage, under the Homebridge storage path | | Your last 5 cleans | homebridge-dyson-vis-nav/cleans/ under the Homebridge storage path — each clean's map as Dyson's cloud returned it, about 400 kB per clean |

Credentials in config.json are normal for Homebridge plugins, but worth knowing: anything that can read your Homebridge configuration — including a configuration backup — can read that password.

Your password is used only to exchange the emailed code for an access token. From then on the plugin authenticates with the token and never reads the password again, so you can remove it:

  • Once the box shows ✓ Authorised, click Forget password, then Save.
  • The plugin carries on working. Enter the password again only if you need to authorise afresh, for instance after Dyson revokes the token.

The plugin checks the token whenever you open the settings, and offers a new code by itself if Dyson has stopped accepting it.

Step 4 — Add the robot to the Home app

The robot is not part of the Homebridge bridge you have already paired. Apple does not accept bridged robot vacuums, so Homebridge publishes it as a device of its own, with its own pairing code.

  1. In the Homebridge log, look for a block like:

    📱 Commissioning codes for Dyson 360 Vis Nav:
       Manual Pairing Code: 1234-567-8901

    You can also find it in the Homebridge UI under Matter.

  2. In the Home app: + → Add Accessory → More options…

  3. Pick your robot from the list, or enter the pairing code by hand.

  4. Choose a room and a name, and you are done.


Everyday use

Where the controls are. Tap the tile to open the robot; the cleaning modes sit above the Start button. The tile itself only starts and stops.

Cleaning modes. Auto, Quick, Quiet and Max mirror the modes in the MyDyson app. Choosing one here sets the robot's default mode, the same setting the MyDyson app shows.

Rooms with their own setting. In the MyDyson app you can give an individual room its own cleaning strategy. Those settings live in Dyson's cloud and this plugin never changes them — so a room set to Max keeps cleaning at Max even when the default is Quick. While a clean is running, the Home app shows the mode the robot is actually using, not the default.

When the robot is out of reach. If it stops responding — off its dock in a dead spot, or the network is down — the plugin keeps showing the last state it saw for a couple of minutes, so a brief dropout does not make the tile flicker. After that it reports the robot's activity as unknown rather than claiming it is still cleaning. The wait is adjustable (Unreachable Timeout).

Maps of recent cleans

Open the plugin's settings in Homebridge and switch to the Recent Cleans tab. It lists your last 5 cleans, newest first:

  • when the clean finished
  • how much floor it covered, and how long it took
  • how often the robot had to recharge, if it did
  • the rooms it cleaned — rooms it only drove through on the way are left out

Select a clean to see its map, drawn at full resolution — one pixel for every 2 cm of floor — with the rooms you set up in the MyDyson app, each in its own colour and with its name:

| On the map | Means | |---|---| | purple → red → orange → yellow → white | cleaned floor, coloured by how much dust the robot picked up there; the brighter, the dirtier | | dark, tinted | a room that this clean did not cover, one tint per room | | white lines | walls | | blue dot | the dock | | yellow dot | where the robot reported a fault | | black | outside your map |

The map is drawn from the cloud data stored with each clean when you open it, so every stored clean has one.

Floor plan or as mapped. The switch above the map picks how the rooms are drawn, and your browser remembers the choice:

  • Floor plan (the default) tidies the rooms into a plan. The robot maps a room only as far as it can drive, so furniture leaves it ragged: a bed is a hole, a wardrobe along a wall takes 60 cm off the room. Each room is squared off into a rectangle, or a few rectangles for an L- or T-shaped hallway. Walls then line up: rooms meet without gaps, and rooms along the same outside wall end at the same line. A room that stops short of its neighbour, say where a bath stands, is extended to meet it.
  • As mapped shows the rooms exactly as the robot recorded them, with every piece of furniture outlined in white and grey lines where one room meets the next.

The floor plan assumes straight walls at right angles. Sloping walls and bay windows come out as rectangles. If a room looks wrong, check it under As mapped: a room that runs into its neighbour there was mapped that way, and is fixed by editing the room in the MyDyson app.

Where the maps come from. When the robot finishes a clean, the plugin asks Dyson's cloud for the clean's map — the same data the MyDyson app shows — and stores it locally, keeping the last five. Dyson's cloud keeps about as many, but the stored copy means the list keeps working when the cloud does not answer or the authorisation has lapsed.

Right after installing. When the plugin starts and has no clean stored yet, it fetches the most recent one from the cloud once, so the list does not start empty. Earlier cleans are not fetched. A clean stored this way shows no duration, because the plugin was not watching while it ran.

Starting over. Reset data below the map deletes every stored clean. Click it twice: the first click turns it into SURE?, and only a second click within five seconds deletes. The list then fills again from the next clean — or, if Homebridge restarts before then, from the most recent clean in the cloud, as after installing.

What it needs. The MyDyson account from Step 3. Without it the plugin cannot reach the maps and the list stays empty.

Maps in the log as well. Set Clean Map Logging to draw each map into the Homebridge log too, as coloured text: the same colours, with ○ for the dock, ‼ for a fault and dotted room boundaries. Pick Homebridge for the log viewer in the Homebridge UI, whose font would scramble the Monospaced style, and Monospaced for a terminal (tail -f over SSH). The map in the log appears shortly after the clean ends, once the plugin has fetched it.


Settings

Everything below has a sensible default; you can ignore all of it.

| Setting | Default | What it does | |---|---|---| | Name | Dyson 360 Vis Nav | The name shown in the Homebridge log | | Serial Number Allow List | empty | Leave empty to add every robot vacuum in your account. Add serial numbers to pick specific ones | | Use simple RVC Clean Mode tags | on | Describes each cleaning mode with one tag instead of several. Turn off only if your controller needs the full set | | Subscribe to wildcard MQTT topic | off | Listens to everything the robot publishes. Useful when capturing a log for a bug report | | Clean Map Logging | Off | Also draws the map of each finished clean into the Homebridge log. The settings page shows the maps either way | | Unreachable Timeout | 120 s | How long the robot may stay silent before the Home app is told its activity is unknown | | Enable debug logging | off | Much more detail in the log | | Debug Features | none | Individual extras — API headers and bodies, MQTT payloads. Turn these on only when asked to |

The settings page writes this block for you; you only need it if you edit config.json by hand. platform must read exactly as shown — it is what ties the block to this plugin — and dysonAccount has to be there for the default "Remote Account" method. Every key that has a default below may be left out.

{
    "platform": "DysonVisNav",
    "name": "Dyson 360 Vis Nav",
    "provisioningMethod": "Remote Account",
    "dysonAccount": {
        "email": "[email protected]",
        "password": "your-mydyson-password",
        "country": "GB"
    },
    "whiteList": [],
    "simpleModeTagsRvc": true,
    "wildcardTopic": false,
    "logMapStyle": "Off",
    "unreachableTimeout": 120,
    "debug": false,
    "debugFeatures": []
}

| Key | Type | Default | What it does | |---|---|---|---| | platform | string | — | Must be "DysonVisNav". The only required key | | name | string | "Dyson 360 Vis Nav" | Name shown in the Homebridge log | | provisioningMethod | string | "Remote Account" | "Remote Account" uses your MyDyson account. "Mock Devices" replays a recorded MQTT session instead, for development — see CONTRIBUTING.md | | dysonAccount | object | — | The MyDyson account to read devices from; see below | | whiteList | string[] | [] | Serial numbers to expose. Empty exposes every robot vacuum in the account | | simpleModeTagsRvc | boolean | true | Advertise one Matter clean-mode tag per cleaning mode instead of the full set. Turn off only if your controller needs all of them | | wildcardTopic | boolean | false | Subscribe to every MQTT topic the robot publishes. Useful when capturing a log for a bug report | | logMapStyle | string | "Off" | Draw a map of each finished clean into the log: "Off", "Monospaced" for a terminal, or "Homebridge" for the log viewer | | unreachableTimeout | integer | 120 | Seconds the robot may stay silent before Apple Home is told its activity is unknown. Between 10 and 3600 | | debug | boolean | false | Much more detail in the log | | debugFeatures | string[] | [] | Individual extras, any of "Log API Headers", "Log API Bodies", "Log MQTT Client", "Log MQTT Payloads", "Log MQTT Payloads as JSON", "Log Serial Numbers", "Log Debug as Info" |

Inside dysonAccount:

| Key | Type | Default | What it does | |---|---|---|---| | email | string | — | The address your MyDyson account uses. It also keys the stored access token | | password | string | — | Optional. Used only to exchange the emailed code for a token, so it can be removed afterwards — see What is stored, and where | | country | string | "GB" | Two-letter code for the country your MyDyson account belongs to | | token | string | — | Optional. Supply an access token yourself instead of authorising through the settings page. It takes precedence over the stored one |

A key the plugin does not know is ignored, with a warning in the log naming it, so a typo is visible rather than silently ineffective.

country selects the Dyson server — mainland China has its own — and the language that per-device requests ask for. Configurations from before this field are migrated on startup: a "china": true flag becomes "CN", and anything else becomes "GB".


If something goes wrong

The plugin warns about Matter and publishes a switch. Matter is not switched on for the bridge this plugin runs on, so the robot is published as a switch, a battery and a problem sensor rather than as a robot vacuum. Go back to step 2 — note that enabling it on the main bridge does not enable it for a plugin sitting in a child bridge, or the other way round.

The switch disappeared after I enabled Matter. That is deliberate. With Matter on, the robot is published as its own Matter accessory, and the switch it replaces is removed so that one robot does not leave you with two tiles. The Matter accessory has its own pairing code — see step 4.

The robot does not appear in the Home app. It has its own pairing code and is not part of your Homebridge bridge — see step 4. Adding the Homebridge bridge again will not bring it in.

No email arrives after Request code. Check your spam folder, and that the email address matches your MyDyson account exactly. If the settings page shows a red message, its wording says whether Dyson refused the request or the plugin failed before reaching them.

"Too many requests" when requesting a code. Dyson rate-limits this. Your earlier request is still valid — use the code from the most recent email rather than asking for another.

The tile says the robot is cleaning when it is not. It stopped responding while cleaning. After Unreachable Timeout the plugin reports its activity as unknown. Lower the value if two minutes feels long.

It cleans at full power even though a gentler mode is set. A room can carry its own cleaning strategy, set in the MyDyson app, which overrides the default for that room. Change it there.

Anything else. Switch on Enable debug logging, reproduce the problem, and open an issue with the log. If it concerns the robot's behaviour rather than the plugin's, add Log MQTT Payloads as JSON under Debug Features — that is what makes such reports diagnosable.


Good to know

Cloud only. Unlike the older 360 Eye and 360 Heurist, the Vis Nav does not accept local connections. Everything goes through Dyson's gateway, the same route the MyDyson app takes, so the robot needs internet access and so does Homebridge.

Matter events are not sent. Homebridge 2.4.0 has no way to emit them, so error and completion events are written to the log instead. The matching attributes are updated normally, and those are what the Home app reads — so you will not notice this in use.

Reachability. Matter carries this on a cluster that Homebridge's plugin API cannot address, so an unresponsive robot is conveyed through its operational state instead, as described above.


For developers

Architecture, how to adopt upstream fixes, the build-time checks, running against a recorded session, and the Homebridge settings-UI pitfalls this project ran into are all in CONTRIBUTING.md.


Credits

The hard part — reverse-engineering Dyson's cloud API and MQTT protocol — is the work of Alexander Thoukydides in matterbridge-dyson-robot. This plugin carries that work over to Homebridge under the ISC licence. If it is useful to you, please consider sponsoring him.

Licence

ISC — see LICENSE.

Dyson, Dyson 360 Vis Nav and MyDyson are trademarks of Dyson Technology Limited. This project is not affiliated with, endorsed by, or supported by Dyson. Apple, HomeKit, Siri and Apple Home are trademarks of Apple Inc.