fix(messages): skip map-related legacy fallback for mower devices#1565
Merged
edenhaus merged 7 commits intoMay 7, 2026
Merged
Conversation
When a mower (e.g. Ecovacs GOAT G1, A1600 RTK, A3000 LiDAR Pro) is mowing, its firmware pushes spontaneous `onMapTrace` MQTT messages. They flow through `messages.get_message()` which falls back via `_LEGACY_USE_GET_COMMAND` to `GetMapTrace`, whose parser does not support the on-wire format used by recent mower firmware (observed: 1.15.13). The parse fails inside `_handle_error_or_analyse` and emits a WARNING per push. In one user setup this produced 217 520 `Could not parse getMapTrace` warnings over 3 days (~70 k/day, ~50/min during mowing), bloating the HA `homeassistant.log` and the recorder DB by ~100 MB. Mowers do not expose a `map=` capability in their hardware definitions, so successfully parsed map-trace data would have nowhere to land anyway — the fallback is pure noise on these devices. This adds an optional `device_type` argument to `get_message` and `get_legacy_message`. When the device is a `MOWER`, map-related legacy messages (`onMapTrace`, `onMapSet`, `onMapSubSet`, `onMinorMap`, `onCachedMapInfo`, `onMultiMapState` and their `get/off/report` variants) are skipped silently before reaching the parser. Vacuums and devices with no specified type fall through unchanged. `Device._handle_message` reads `device_type` defensively via `getattr` so existing test mocks that don't expose the dataclass field on `spec_set=Capabilities` continue to work — they fall back to the no-filter path. Tests: - `test_get_messages` (existing 7 cases) — pass unchanged. - `test_get_messages_device_type_filter` (10 new cases) — verify mowers skip map-related legacy fallbacks while non-map messages and other device types remain unaffected. - Full suite: 707/707 pass, no regression. Refs: DeebotUniverse#1376 (Disable getMapTrace for Goat) Refs: DeebotUniverse#852 (GOAT A1600 RTK Support)
This was referenced Apr 29, 2026
edenhaus
requested changes
Apr 29, 2026
Address review feedback on DeebotUniverse#1565: - Drop the explanatory comment block above ``_MAP_LEGACY_COMMANDS`` - Replace the ``device_type == DeviceType.MOWER`` check with a capability-based one. ``get_message`` now takes ``has_map: bool`` (keyword-only) and ``get_legacy_message`` skips map-related fallbacks when the device does not expose a ``map`` capability — independent of whether the device is a mower, vacuum, or future device class. - ``Device._handle_message`` derives ``has_map`` from ``capabilities.map`` via ``getattr`` so test mocks unaffected.
reniko
pushed a commit
to reniko/client.py
that referenced
this pull request
May 1, 2026
GetMapTrace V2 format is better handled by upstream PRs DeebotUniverse#1565 and DeebotUniverse#1567. The xmp9ds test duplicates existing coverage per maintainer feedback on DeebotUniverse#1564. https://claude.ai/code/session_01YFYjxwixRZrtjfv1aUfoVQ
edenhaus
requested changes
May 5, 2026
Address review feedback from edenhaus: - Pass the whole `static: StaticDeviceInfo` object to `get_message()` instead of extracting `data_type` and `has_map` separately at the call site. - Remove `getattr` in device.py — access `capabilities.map` directly since the attribute is defined on the dataclass. - Remove `lru_cache` on `get_message` since `StaticDeviceInfo` contains non-trivially-hashable `Capabilities` objects. The function is cheap enough without caching (string lookups + one regex). - Update tests to use real `StaticDeviceInfo` fixtures (yna5xi with map, xmp9ds without map) instead of passing primitive params. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #1565 +/- ##
==========================================
+ Coverage 94.92% 94.99% +0.06%
==========================================
Files 156 158 +2
Lines 6105 6189 +84
Branches 350 351 +1
==========================================
+ Hits 5795 5879 +84
Misses 248 248
Partials 62 62 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a mower (Ecovacs GOAT G1, A1600 RTK, A3000 LiDAR Pro, …) is mowing, its firmware pushes spontaneous
onMapTraceMQTT messages. They flow throughmessages.get_message()which falls back via_LEGACY_USE_GET_COMMANDtoGetMapTrace, whose parser does not support the on-wire format used by recent mower firmware (observed:1.15.13). The parse fails inside_handle_error_or_analyseand emits aWARNINGper push.In one user setup this produced 217 520
Could not parse getMapTracewarnings over 3 days (~70k/day, ~50/min during mowing), bloating the HAhomeassistant.logand the recorder DB by ~100 MB.Mowers do not expose a
map=capability in their hardware definitions (see0jbd6s,2ap5uq,2i0fns,5xu9h3,aadham,xmp9ds,itk04l), so even if the legacy fallback succeeded, the parsed map-trace data would have nowhere to land. The fallback is pure noise on these devices.Change
Add an optional
device_type: DeviceType | None = Noneargument toget_messageandget_legacy_message. When the device is aMOWER, map-related legacy messages are skipped silently before reaching the parser:Vacuums (
DeviceType.VACUUM) and callers without a specified type (None) fall through unchanged — fully backwards compatible.Device._handle_messagereadsdevice_typedefensively viagetattrso existing tests mockingCapabilitieswithspec_set=(which excludes dataclass field names fromdir()) continue to work — they fall back to the no-filter path.Refs
getMapTrace()for Ecovacs Goat Lawn MowerTest plan
test_get_messages(existing 7 cases) — pass unchangedtest_get_messages_device_type_filter(10 new cases) — verify mowers skip map-related legacy fallbacks while non-map messages and other device types remain unaffected