Bring a Dreame or MOVA robotic mower into Home Assistant with mower-native controls, schedules, maps, live coverage, and camera support.
The integration follows the Dreamehome and MOVAhome app protocol and is tested against real A2-family hardware. Everyday state and controls stay simple, while reverse-engineering probes and riskier maintenance operations remain out of the default dashboard.
For the dashboard shown above, pair this integration with the Lawn Mower Card. Its Hero layout automatically finds the integration's map, mission, coverage, and live video entities when their names follow the normal Home Assistant device naming.
The live-path map combines the stored garden geometry with mower position and the current cut trail. The card warms this image while the Overview tab is open, so switching to Map does not have to begin with a blank frame.
The standard Home Assistant device page remains available for entity discovery and diagnostics:
This project is usable, but still young. Core mower state, controls, schedules, maps, and diagnostics are available. Some features remain diagnostic or disabled by default while the protocol is validated across more models.
Support levels in this table mean:
Validated: exercised against real hardware and fixtures in this repositoryRecognized: model strings, account types, or rebadges are known and should degrade gracefully, but still need more real-world confirmationNeeds reports: intended target, but not yet proven enough to claim support
| Scope | Status | Notes |
|---|---|---|
Dreame A2 (dreame.mower.g2408) |
Validated | Primary live development device, including schedules, maps, remote control, guarded preference writes, and diagnostics |
MOVA LiDAX Ultra 1000 (mova.mower.g2529c) |
Recognized | Added from a MOVAhome EU diagnostics report; commands and battery are reported working, state handling now accepts model-specific cloud property ids |
Dreame A3 AWD Pro 3500 (dreame.mower.g2541e) |
Recognized | Added from a Dreamehome EU diagnostics report; needs broader live confirmation before it is considered validated |
Dreame A3 AWD 1000 (dreame.mower.q2501a) |
Recognized | Core entities, maps, and mower state are field-confirmed on firmware 4.3.6_0418; live video still needs model-specific runtime proof |
Newer A-series mower (dreame.mower.g3255) |
Recognized | Raw model has been observed in code mapping, but the public retail name is still unverified |
Dreame A1 (dreame.mower.p2255) |
Recognized | Model mapping is present; needs fixtures and live validation |
Dreame A1 Pro (dreame.mower.g2422) |
Recognized | Model mapping is present; needs fixtures and live validation |
| MOVAhome accounts | Recognized | Login flow and account type are supported; needs broader live confirmation |
| MOVA-branded mower rebadges | Needs reports | Expected to follow the same protocol family, but still needs sanitized fixtures and user reports |
| Regional / firmware variants of known A-series models | Needs reports | Should avoid crashing, but behavior can still vary by firmware and region |
Current live validation is still centered on:
- Dreamehome account in the EU region
- A2-family hardware
If you have a mower model not listed as Validated, please open an issue or PR.
Model reports with sanitized diagnostics, screenshots, raw model identifiers, and
region/account details are especially helpful for moving a device from
Recognized or Needs reports to Validated.
- UI config flow with Dreamehome or MOVAhome account login
- automatic mower discovery from the cloud account
lawn_mowerentity for start, pause, and dock- button to dock without ending the current mowing session
- heartbeat-backed task status and automatic resume of a paused mowing session
- battery, activity, state, task, firmware, and error sensors
- active-map selector that switches the mower, plus mowing action, edge, zone, and spot selectors that follow the selected map
- current-map services for switching maps and starting explicit zone, spot, or edge runs
- binary sensors for docked, charging, mowing, paused, returning, and error state
- binary sensors for active and resumable mowing sessions
- binary sensor for Bluetooth-connected runtime state
- read-only schedule calendar using the mower-native app schedule protocol
- disabled-by-default all-schedules calendar for default and per-map schedule diagnosis
- guarded schedule enable/disable service with dry-run mode by default
- guarded mowing-preference update service with dry-run mode by default
- read-only map camera using the app-map payload when available, with options for label scale and clockwise display rotation
- disabled-by-default all-maps and map-diagnostics cameras
- live video camera with a managed XP2P runtime on Linux x86_64 and aarch64 hosts
- runtime telemetry sensors for mission progress, mission area, mower pose, and live-track length
- last-session mission progress and coverage retained after docking, explicitly
marked with
cached: trueand acaptured_attimestamp - selected-run sensors for mowing action, chosen map, and scoped zone/spot/edge target
- selected-zone preference sensors for read-only mowing height, efficiency, direction, and obstacle-avoidance details
- read-only weather/rain-protection diagnostics
- read-only weather/rain-protection entities from cached app settings
- read-only mowing-preference diagnostics
- supervised remote-control service for short validation pulses
- sanitized diagnostics and debug snapshot helpers
- cloud presence checks that make entities unavailable instead of showing stale mower values while the device is offline
The following areas are intentionally cautious:
- firmware OTA now exposes a Home Assistant update entity using the app's
approved
checkDeviceVersiontarget andmanualFirmwareUpdateapproval step, but release notes remain best-effort because the live A2 endpoint still embeds amissing langerror string in the changelog field the live Dreame A2 verification on April 22, 2026 completed from4.3.6_0320to4.3.6_0447 - a read-only debug OTA catalog probe exists for version-trace work, but it is not treated as authoritative latest-version, changelog, or install approval data because it is a manual catalog rather than the mobile app's approved OTA response
- firmware diagnostics now include those debug-catalog candidate versions when available, so operation snapshots can show plausible newer builds without conflating them with the app-approved update target
- rain-protection writes are not exposed yet
- mowing-preference writes are guarded, validated on a supervised A2 no-op write, and still need broader model and firmware validation
- map rendering is read-only; no-go editing, virtual-wall editing, and other map editing flows are not exposed yet
- live video has been validated end to end on a Dreame A2, including Home Assistant HLS playback; other Tencent-video mower models and firmware still need field validation
- the managed video runtime currently supports Linux x86_64 and aarch64 Home Assistant hosts, and the mower must be active and away from its station before the vendor permits live video
- 3D map object downloads are metadata-first and not treated as stable
- manual driving must stay supervised and uses strict state and battery guards
-
Add this repository to HACS as a custom integration repository:
If the button does not open your Home Assistant instance, manually add this repository URL in HACS:
https://github.com/EvotecIT/homeassistant-dreamelawnmower -
Install Dreame Lawn Mower from HACS.
-
Restart Home Assistant.
-
Add the integration from Settings -> Devices & services:
Copy custom_components/dreame_lawn_mower into your Home Assistant
custom_components directory, restart Home Assistant, then add the integration
from the UI.
The config flow asks for:
- account type:
dreameormova - country/region
- username
- password
The integration stores Home Assistant config-entry data only. Do not put credentials into repository files, fixtures, or issue attachments.
On Linux x86_64 and aarch64 Home Assistant hosts, the Live Video camera uses
the managed runtime by default. No Android phone, emulator, library path, or
external runner is required. The integration prepares the runtime during entity
setup, starts it when Home Assistant requests the camera, verifies the local FLV
source, and stops it when the camera is turned off or unloaded.
The first setup needs internet access. The integration downloads fixed versions
of Tencent XP2P, the required AOSP Bionic libraries, and qemu-user-static on
x86_64 hosts. Every file is pinned and SHA-256 verified before use, then cached
under Home Assistant's .storage directory. The Home Assistant/Python client
owns the lifecycle; Tencent's proprietary P2P transport still runs in the small
native compatibility worker. It does not require an Android device or Android
framework.
The Dreame A2 proof uses a normal copied custom_components installation, the
real Home Assistant mower and camera entities, and Home Assistant's HLS output.
The retained H.264 MP4 reopened independently as 640 x 360 video and decoded
100 frames spanning 6.599 seconds. The HA camera entity also returned a real
JPEG through the integration's PyAV/Pillow still-image path, even without the
optional TurboJPEG system library, and that frame was visually inspected. This
is a pixel-level playback proof, not only an FLV header or byte-count check.
The mower vendor only allows video while the mower is active and away from its station. Requesting the camera does not start or move the mower. The existing native-library and persistent-runner options remain available as advanced overrides for development or unsupported host platforms.
The integration exposes two video transport policies. The default uses the
proven cloud-provisioned XP2P path. Auto can restart from health-checked cached
provisioning and lets Tencent negotiate the available network route. It also
probes Tencent's separate same-LAN service when mower firmware advertises one.
The tested A2 production firmware does not advertise that service, so the
integration does not offer a LAN-only policy. The camera's
last_stream_session attribute reports stream_route as direct only when
the separate LAN service was selected; otherwise it stays unknown. Tencent's
misleadingly named getStreamLinkMode API returns a network/NAT-type bitmask,
exposed as sdk_stream_network_type, rather than a direct-versus-relay result.
After a successful cloud-provisioned stream, Auto privately caches the minimum
XP2P identity, P2P material, QCloud/app credentials, and resolved device
configuration under Home Assistant's .storage. The cache uses Home Assistant's
private-store permissions and deliberately excludes the Dreame access token,
LAN discovery token, and raw cloud responses. On a later restart, Auto tries
that cache before any Dreame video-input or camera-toggle call and refreshes it
through the normal path if the cached material has expired.
This proof is intentionally narrower than every camera feature in the vendor apps:
- In one captured A2 session, normal-XP2P AUTO media travelled directly between
the Home Assistant host and the mower's same-LAN IP. A retained socket trace
includes the direct peer address, FLV request, HTTP 200 response, and media
bytes, so this does not depend on an SDK label. Tencent's separate WLAN
discovery and
startLanServicepath was also implemented, but this A2 firmware did not answer that discovery request. Dreame/Tencent cloud calls still provide the initial provisioning.Autocan reuse health-checked video provisioning without fetching new video inputs or toggling the camera through Dreame cloud, but it first refreshes the mower snapshot and refuses to start when current safety state cannot be verified. Tencent XP2P can also use its internet rendezvous/STUN control plane to establish the direct peer route. Neither transport policy promises startup with all internet connectivity removed. - Home Assistant can display and save the current JPEG frame, but the vendor's stored photo gallery is not exposed.
- Live video is field-validated on the A2 only. A3 AWD Pro and MOVA camera variants still need their own runtime-input and playback proof.
- Patrol movement, arbitrary voice-prompt playback, and two-way live talk are separate control/audio features and are not implemented by this camera.
Maintainers can find the confirmed protocol split, A2 findings, retained LAN implementation, and future device validation checklist in Video Transport and Same-LAN Research.
Support across Dreame, MOVA, and rebadged mower variants will improve fastest with real-world reports. If your mower is recognized but not yet validated, or if it exposes a different raw model string than this README shows, please open a GitHub issue or PR with:
- the retail product name and raw app/cloud model identifier
- account type (
dreameormova) and region - a sanitized diagnostics capture or Home Assistant debug snapshot
- screenshots of the product page, app model name, or device information page
- notes about what works, what is missing, and any errors you see
Please redact credentials, tokens, serial numbers, exact coordinates, and any other secrets before attaching files.
The primary entity is:
lawn_mower.<device>
Common user-facing helpers include:
sensor.<device>_activitysensor.<device>_state_namesensor.<device>_errorsensor.<device>_batterysensor.<device>_mowing_progresssensor.<device>_selected_mowing_actionsensor.<device>_selected_mapsensor.<device>_selected_targetsensor.<device>_selected_zone_mowing_heightsensor.<device>_selected_zone_efficiency_modesensor.<device>_selected_zone_direction_modesensor.<device>_selected_zone_obstacle_avoidancesensor.<device>_selected_zone_obstacle_distancesensor.<device>_selected_zone_obstacle_heightsensor.<device>_selected_zone_obstacle_classessensor.<device>_runtime_mission_progresssensor.<device>_runtime_current_areasensor.<device>_runtime_total_areasensor.<device>_runtime_live_track_lengthsensor.<device>_runtime_live_track_point_countsensor.<device>_weather_protection_statusselect.<device>_mapselect.<device>_mowing_actionselect.<device>_edgeselect.<device>_zoneselect.<device>_spotbinary_sensor.<device>_dockedbinary_sensor.<device>_chargingbinary_sensor.<device>_bluetooth_connectedbinary_sensor.<device>_mowingbinary_sensor.<device>_task_activebinary_sensor.<device>_task_resumablebinary_sensor.<device>_rain_delay_activebinary_sensor.<device>_returningcalendar.<device>_schedulecamera.<device>_live_videoon supported Linux hosts
Many reverse-engineering and validation helpers are disabled by default. Enable them from the entity registry only when troubleshooting:
- map and all-map cameras
- map diagnostics camera
- runtime pose / heading / segment-count sensors
- all-schedules calendar
- rain delay end time sensor
- last schedule probe/write sensors
- last task-status, weather, and preference probe sensors
- raw vendor flag sensors
- manual-drive safety diagnostics
Dreame A2 schedules can exist in more than one slot. Live captures have shown a
default schedule plus per-map schedules. The normal Home Assistant Schedule
calendar follows the active schedule version reported by the mower's SCHDT
response, so hidden/default/other-map schedules do not appear as normal mowing
events.
Enable the disabled All Schedules calendar only when you intentionally want to
inspect every decoded schedule slot.
The guarded dreame_lawn_mower.set_schedule_plan_enabled service is dry-run
first. It sends a write only when both execute: true and
confirm_schedule_write: true are set.
dreame_lawn_mower.plan_mowing_preference_update is dry-run first. It reads
the current app preference payload, applies the requested field changes
locally, and exposes the candidate PRE request in a notification plus the
disabled-by-default Last Preference Write diagnostic sensor. It sends a live
preference write only when both execute: true and
confirm_preference_write: true are provided.
The guarded preference fields include per-zone safe edge mowing through
edge_mowing_safe. Use the dry-run result to inspect the candidate payload
before confirming a live write.
The map camera uses the confirmed app-map JSON path first. The renderer is read-only and produces a simple Home Assistant camera image from the decoded map payload.
Enabled map cameras warm their first image in the background during entity startup. After that, the camera returns the last rendered JPEG immediately while a map older than 60 seconds refreshes in the background. Identical source images reuse the existing JPEG conversion. This cache is intentionally in memory: a Home Assistant restart rebuilds it from the mower rather than persisting garden geometry to a second on-disk store.
The runtime mission progress, current-area, and total-area sensors also retain
the latest useful session values after mowing stops. While mowing they represent
live telemetry; after docking their attributes include cached: true and
captured_at. They become live again as soon as a new runtime session reports
metrics. This keeps dashboards useful without presenting an old mower position
or trail as current.
If the mower has multiple maps, enable the disabled All Maps camera to render
a contact sheet. Use Map Diagnostics when the map image is missing or when you
need source, counts, and parser evidence.
Current map support now includes:
- a read-only
Mapcamera for the active map - a read-only
All Mapscontact sheet for quick map inventory - a
Mapselect that switches the mower's active map and refreshes the map, zone, spot, and edge controls selectentities for mowing action, edge, zone, and spot scope- services for switching the active mower map and starting explicit zone, spot, or edge jobs
- runtime live-track telemetry surfaced through sensors and map-camera attributes
- circular and rotated rectangular forbidden areas rendered from their compact mower map representation
Interactive map editing is still intentionally out of scope for now:
- no-go editing
- virtual-wall editing
- zone geometry edits
- other direct map mutations
The integration now exposes guarded current-map services on the lawn_mower
entity:
dreame_lawn_mower.switch_current_mapdreame_lawn_mower.start_zone_mowingdreame_lawn_mower.start_spot_mowingdreame_lawn_mower.start_edge_mowing
These use current decoded app-map and vector-map metadata. Map switching updates
the real active mower map, while zone, spot, and edge starts target explicit
current-map ids rather than relying only on the generic Home Assistant
start_mowing action.
For example, this starts the saved zone with ID 1 on the mower's active map:
action: dreame_lawn_mower.start_zone_mowing
target:
entity_id: lawn_mower.a3_awd_pro_3500
data:
zone_ids: [1]Use entity_id when the value starts with lawn_mower.. A Home Assistant
device_id is a separate device-registry identifier and must not contain an
entity ID. The lawn mower entity exposes available_zone_ids, and zone selects
use names saved in the Dreame app when vector-map metadata provides them. An
unnamed zone retains the stable Zone #<id> fallback.
Zone, spot, and edge actions are acknowledged by the mower before Home Assistant reports success. Unknown current-map IDs, map-scope mismatches, and device rejection responses are surfaced as failed actions.
Start with a fresh Home Assistant diagnostics capture:
- Reproduce the problem once.
- Before reloading or restarting Home Assistant, open the integration or device page and download diagnostics.
- Attach the downloaded JSON to the issue. Add screenshots or short log excerpts only when they show something that is not already in the diagnostics.
The report is sanitized by the integration and includes:
- the installed integration, Home Assistant, Python, operating-system, and CPU architecture versions
- config-entry and coordinator health
- current state and diagnostic attributes for every entity belonging to the config entry, including the Live Video camera's last failure stage and a bounded, privacy-safe summary of each TX video cloud stage
- a bounded list of recent coordinator, map, schedule, and video failures with repeated failures coalesced
- the existing
triage,state_reconciliation, schedule, map, firmware, and raw property summaries
Do not enable broad debug logging unless a maintainer asks for a specific logger. Cloud protocol debug output can contain data that needs additional review before it is posted publicly.
The staged cloud summaries retain field names, value types, safe status codes, required-field presence, and sanitized error messages. They do not retain raw response values, account or device identifiers, credentials, stream URLs, or unbounded payloads. This lets maintainers distinguish unsupported models, malformed vendor responses, and missing provisioning without asking users to share an account as the first debugging step.
For issue reports, include:
- the downloaded diagnostics captured immediately after the failure
- what you expected and the exact steps that failed
- whether the same operation worked in Dreamehome or MOVAhome at that time
- screenshots only when the visible result matters
Home Assistant log lines that start with Captured Dreame lawn mower ... can be
converted to JSON with:
python examples/extract_ha_payload.py home-assistant.log --summaryThis repository ships two usable layers:
dreame_lawn_mower_clientfor direct Python access to Dreame/MOVA mower cloud, app-action, schedule, map, and diagnostic APIs- the Home Assistant integration in
custom_components/dreame_lawn_mower
Library docs: docs/python-library.md
Runnable example: examples/python_client.py
Example:
from dreame_lawn_mower_client import DreameLawnMowerClient
devices = await DreameLawnMowerClient.async_discover_devices(
username=username,
password=password,
country="eu",
account_type="dreame",
)
client = DreameLawnMowerClient(
username=username,
password=password,
country="eu",
account_type="dreame",
descriptor=devices[0],
)
snapshot = await client.async_refresh()
print(snapshot.descriptor.title, snapshot.mower_state_name, snapshot.battery_level)The Home Assistant integration uses the same client package name inside the
custom component bundle, so HACS installs the protocol layer together with the
integration while scripts and tests can still import dreame_lawn_mower_client
directly.
Install development dependencies:
python -m pip install -e .[test]Run checks:
python -m compileall dreame_lawn_mower_client custom_components tests examples
pytestUseful docs:
Read-only probes are preferred. Anything that can move the mower or write mower settings must remain supervised, explicitly confirmed, and safe-state guarded.


