Skip to content
Hack Your WorldSoftware · Infrastructure · Home automation

Analysis

Add the Eufy Omni S2 to Home Assistant with Matter

My Eufy Omni S2 can clean a selected room through Home Assistant without a custom Eufy integration. I paired it through Matter, mapped its rooms, and added mode selection and a stuck-vacuum alert. The Eufy app still handles the map and appliance settings.

A robot vacuum, cleaning dock, and local Matter connection in a home
AI image: Hack Your World
In this article

Why this is a new setup, not an S1 migration

The previous vacuum here was an Eufy S1 Pro. Lightning took it out. The configuration repository still contains an old custom component with that model in its name, but it is not what controls the current vacuum.

The S2 is paired through Home Assistant’s Matter integration. Home Assistant identifies it as an Anker Innovations Technology “eufy Robot Vacuum,” with eleven entities attached to the device. That distinction matters because the useful controls come from the standard Matter vacuum model, not from an abandoned S1 component or a cloud workaround.

What the S2 exposes in Home Assistant

Piece What I use it for
vacuum.s2 Start, pause, dock, and clean mapped areas.
select.s2_clean_mode Choose vacuum-only, mop-and-vacuum, deep, quick, low-noise, or Eufy’s custom mode.
Operational state Tell whether the S2 is docked, charging, cleaning, or looking for its charger.
Operational error Trigger an alert when the vacuum reports a problem.
Battery and charge state Useful in principle, but the percentage is not trustworthy in this setup yet.

The clean-mode selector currently offers eight choices: Auto Mop & Vacuum, Auto Vacuum, Auto Deep Mop & Vacuum, Quick Mop & Vacuum, Quick Vacuum, Low Noise Mop & Vacuum, Low Noise Vacuum, and Eufy Customize Mode.

The part that makes room cleaning work

The Eufy app knows its own map and room boundaries. Home Assistant has a separate list of areas. I mapped the vacuum’s segments to Home Assistant areas once in the vacuum entity settings. After that, scripts can use readable area IDs instead of Eufy’s private segment numbers.

Home Assistant added the standard vacuum.clean_area action in 2026.3, with Matter among the first supported platforms. That is the key. The automation no longer needs to know that the kitchen happens to be segment 7 today.

Check the room mapping before building a script

First confirm that the vacuum entity offers area mapping in its settings. Map one vacuum segment to one Home Assistant area, then try vacuum.clean_area with that single area from the Actions interface. The command starts cleaning: choose an accessible room and watch where the vacuum goes.

target.entity_id selects the vacuum. cleaning_area_id selects the mapped rooms to clean; it is not the area containing the dock. Use the IDs Home Assistant supplies, not the display names or Eufy’s raw segment numbers. If the mapping controls are missing, check the device’s exposed features before copying the scripts. See the clean-area action documentation.

One room

This is a complete script for the script editor’s YAML view. Replace vacuum.s2 and select.s2_clean_mode with your entity IDs, and check that the selector offers the exact option strings used below.

My first script accepts a Home Assistant area and a simple choice between vacuuming and vacuuming plus mopping. It sets the S2 mode, waits one second for that choice to land, then starts the mapped area.

alias: S2 Clean Room
mode: restart
fields:
  area:
    name: Area
    required: true
    selector:
      area: {}
  mode:
    name: Mode
    default: Vacuum + Mop
    selector:
      select:
        options:
          - Vacuum
          - Vacuum + Mop
sequence:
  - action: select.select_option
    target:
      entity_id: select.s2_clean_mode
    data:
      option: >-
        {{ 'Auto Vacuum' if mode == 'Vacuum'
           else 'Auto Mop & Vacuum' }}
  - delay: "00:00:01"
  - action: vacuum.clean_area
    target:
      entity_id: vacuum.s2
    data:
      cleaning_area_id: "{{ [area] }}"

The area selector is the important usability detail. When I call the script from an automation or the Home Assistant interface, I choose a normal room instead of typing an ID.

Several rooms and the whole floor

The zone version uses the same sequence but allows several areas. It also exposes every exact clean mode reported by the S2, while keeping “Vacuum” and “Vacuum + Mop” as the easy choices.

- action: vacuum.clean_area
  target:
    entity_id: vacuum.s2
  data:
    cleaning_area_id: "{{ areas }}"

The whole-house script is deliberately boring. It contains a fixed list of the mapped areas I want cleaned and sends that list to the same action. I do not include utility spaces or every bedroom just because they exist in Home Assistant. “Whole house” means the normal cleaning route for this floor, not every area in the database.

The alert I actually wanted

A vacuum rarely needs an elaborate dashboard. It needs to tell me when it failed quietly. My automation creates a persistent Home Assistant notification in either of two cases:

  • The operational-error sensor changes away from no_error.
  • The S2 spends eight minutes seeking its charger, which usually means a closed door or a physical trap.

The full example below adapts those triggers and adds a filter so unknown or unavailable is not reported as a mechanical fault. Paste it into a new automation’s YAML editor and replace the sensor IDs. Download the YAML.

# Adapted example for the Home Assistant automation editor's YAML view.
# Replace both sensor entity IDs. No vacuum commands are sent.
alias: S2 needs attention
mode: queued
max: 5
triggers:
  - trigger: state
    entity_id: sensor.s2_operational_error
    to: null
    id: error
  - trigger: state
    entity_id: sensor.s2_operational_state
    to: seeking_charger
    for: "00:08:00"
    id: charger
conditions:
  - condition: template
    value_template: >-
      {{ trigger is defined and
         (trigger.id == 'charger' or
          (trigger.id == 'error' and trigger.to_state is not none and
           trigger.to_state.state not in ['no_error', 'unknown', 'unavailable'])) }}
actions:
  - action: persistent_notification.create
    data:
      notification_id: "s2_{{ trigger.id }}"
      title: S2 needs attention
      message: >-
        {% if trigger.id == 'charger' %}
          The S2 has been seeking its charger for eight minutes.
          Check the route to the dock and the vacuum itself.
        {% else %}
          The S2 reported: {{ trigger.to_state.state }}.
          Check the vacuum and its Eufy app before restarting a clean.
        {% endif %}

The YAML and template conditions have been checked with offline test cases. That is not an end-to-end test on another S2. Verify the sensor state strings in your own installation and inspect the automation trace when a real state transition occurs.

This creates a persistent notification inside Home Assistant, not a phone push. Repeated alerts of the same type update one notification; it stays until dismissed. Home Assistant’s timed triggers reset when automations reload or Home Assistant restarts, so the eight-minute condition is not a durable timer.

I prefer an exception alert to a message after every successful run. Silence is not proof of success, though: these two triggers do not cover a disconnected vacuum, an unavailable sensor, or Home Assistant being offline.

What is still rough

During the setup documented here, the device reported 0% battery while the charge-state entity said “Full charge.” I am not using the percentage in automations until that contradiction is fixed. The device history also flips rapidly among docked, charging, and not charging while it sits at the station. The broad operational state is useful; the fine-grained charging telemetry is noisy.

Matter also does not replace the Eufy app. Home Assistant can issue the cleaning job and observe the important state, but the Eufy app remains the place for the rich map, map editing, station settings, obstacle details, and model-specific tuning. The split is acceptable: local automation in Home Assistant, detailed appliance management in the vendor app.

I would not buy the S2 just because it has Matter

Matter makes the S2 easier to fit into the rest of my house. It does not turn Home Assistant into a replacement for the Eufy app, and it does not prove that the vacuum is worth its asking price for somebody else. The local controls I verified are useful because I already want the S2 to clean: room targeting, mode selection, docking, and failure alerts. They are not the product’s whole value.

If Home Assistant were my only requirement, I would not pay flagship-vacuum money for this integration alone. I would first decide whether the station, roller mop, carpet behavior, obstacle handling, consumables, and app experience justify the machine. Then I would treat Matter as the clean automation boundary—not the buying reason.

What I can verify for a buyer
Question Answer from this setup
Can Home Assistant start a specific room? Yes, after the Eufy map segments are mapped to Home Assistant areas.
Can it choose vacuum or mop modes? Yes. The current Matter device exposes eight named modes.
Can Home Assistant replace the Eufy app? No. Mapping, detailed appliance settings, and model-specific features remain in the vendor app.
Is every sensor trustworthy? No. This unit has reported 0% battery beside a full-charge state, so I exclude battery percentage from automations.
Which listing matches the current US S2? Eufy’s current US product page identifies retail variant T2081111. I have not reopened the physical unit to confirm that product number, so I am keeping that distinction visible.

Eufy’s maintenance guidance calls for cleaning the dirty-water tank, dustbin, roller, brushes, and sensors regularly, with accessory replacement driven by the app’s wear reminders. That recurring work belongs in the buying decision. An all-in-one station reduces daily handling; it does not eliminate ownership.

If the script runs but the clean is wrong

  • Wrong room: check the vacuum-to-area mapping, especially after editing or replacing a map. A valid area name cannot repair a stale mapping.
  • Wrong cleaning mode: compare the selector options and read its state after the action. The one-second delay in my script is a pause, not an acknowledgement from the robot.
  • No alert: check the error sensor and automation trace. A successful manual run of the notification action tests message delivery, not the state triggers or eight-minute wait.
  • Unavailable entities: start with Matter connectivity. Do not diagnose a mechanical fault from missing telemetry.

Would I add it this way again?

Yes. The setup gives Home Assistant the controls that matter to the rest of the house without putting a third-party password-based integration in the middle. The scripts use standard actions and area names, so they are readable and easy to call from buttons, schedules, or presence automations.

I would not build anything important on the battery percentage yet, and I would keep the one-second delay after changing the cleaning mode. I would also keep the scripts thin. The S2 already knows how to navigate and clean; Home Assistant only needs to tell it where, how, and when.

References: Home Assistant 2026.3 area-cleaning release · Home Assistant clean-area action · Eufy Omni S2 product and maintenance information

Based on my Omni S2 setup. The downloadable alert is an adapted example, checked offline as described above.