From 7ab01f7fc251d97526dcdb2daa6998da6835964a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Besson?= Date: Thu, 14 May 2026 15:03:29 +0200 Subject: [PATCH] feat(hardware): expose CleanAreaV2 capability on the 4 mower models MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `area=CleanAreaV2` to `CapabilityCleanAction` for the GOAT family (xmp9ds A1600 RTK, 5xu9h3 G1, 51rcxt A3000 LiDAR Pro, 300lc5 O500 Panorama). The mowers already accept the same `clean_V2` payload with `{"act":"s","content":{"type":"spotArea","value":""}}` — verified via MQTT sniff on a real A1600 (Trampo zone id=1 confirmed). Consumers (e.g. home-assistant/core) can now invoke `device.capabilities.clean.action.area(CleanMode.SPOT_AREA, [zone_id], 1)` to launch a specific zone on a mower without falling back to the `Map complete` action. `getAreaSet type:"ar"` returns the zone definitions (LZMA+base64 encoded) with stable numeric IDs that map to the named zones in the Ecovacs app, enabling clients to build a zone-name → id lookup at runtime. The `CleanAreaV2` API itself is unchanged — this is a pure capability exposure on hardware definitions. --- deebot_client/hardware/300lc5.py | 4 ++-- deebot_client/hardware/51rcxt.py | 4 ++-- deebot_client/hardware/5xu9h3.py | 4 ++-- deebot_client/hardware/xmp9ds.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/deebot_client/hardware/300lc5.py b/deebot_client/hardware/300lc5.py index 2a350d9a7..da5263ca7 100644 --- a/deebot_client/hardware/300lc5.py +++ b/deebot_client/hardware/300lc5.py @@ -34,7 +34,7 @@ from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.charge import Charge from deebot_client.commands.json.charge_state import GetChargeState -from deebot_client.commands.json.clean import CleanV2, GetCleanInfoV2 +from deebot_client.commands.json.clean import CleanAreaV2, CleanV2, GetCleanInfoV2 from deebot_client.commands.json.custom import CustomCommand from deebot_client.commands.json.error import GetError from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan @@ -81,7 +81,7 @@ def get_device_info() -> StaticDeviceInfo: battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), clean=CapabilityClean( - action=CapabilityCleanAction(command=CleanV2), + action=CapabilityCleanAction(command=CleanV2, area=CleanAreaV2), ), custom=CapabilityCustomCommand( event=CustomCommandEvent, get=[], set=CustomCommand diff --git a/deebot_client/hardware/51rcxt.py b/deebot_client/hardware/51rcxt.py index d87374188..43734d855 100644 --- a/deebot_client/hardware/51rcxt.py +++ b/deebot_client/hardware/51rcxt.py @@ -34,7 +34,7 @@ from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.charge import Charge from deebot_client.commands.json.charge_state import GetChargeState -from deebot_client.commands.json.clean import CleanV2, GetCleanInfoV2 +from deebot_client.commands.json.clean import CleanAreaV2, CleanV2, GetCleanInfoV2 from deebot_client.commands.json.custom import CustomCommand from deebot_client.commands.json.error import GetError from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan @@ -81,7 +81,7 @@ def get_device_info() -> StaticDeviceInfo: battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), clean=CapabilityClean( - action=CapabilityCleanAction(command=CleanV2), + action=CapabilityCleanAction(command=CleanV2, area=CleanAreaV2), ), custom=CapabilityCustomCommand( event=CustomCommandEvent, get=[], set=CustomCommand diff --git a/deebot_client/hardware/5xu9h3.py b/deebot_client/hardware/5xu9h3.py index 44170ab3e..10efd7325 100644 --- a/deebot_client/hardware/5xu9h3.py +++ b/deebot_client/hardware/5xu9h3.py @@ -34,7 +34,7 @@ from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.charge import Charge from deebot_client.commands.json.charge_state import GetChargeState -from deebot_client.commands.json.clean import CleanV2, GetCleanInfoV2 +from deebot_client.commands.json.clean import CleanAreaV2, CleanV2, GetCleanInfoV2 from deebot_client.commands.json.custom import CustomCommand from deebot_client.commands.json.error import GetError from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan @@ -81,7 +81,7 @@ def get_device_info() -> StaticDeviceInfo: battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), clean=CapabilityClean( - action=CapabilityCleanAction(command=CleanV2), + action=CapabilityCleanAction(command=CleanV2, area=CleanAreaV2), ), custom=CapabilityCustomCommand( event=CustomCommandEvent, get=[], set=CustomCommand diff --git a/deebot_client/hardware/xmp9ds.py b/deebot_client/hardware/xmp9ds.py index 7bfd87c73..3dbc9a67e 100644 --- a/deebot_client/hardware/xmp9ds.py +++ b/deebot_client/hardware/xmp9ds.py @@ -34,7 +34,7 @@ from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.charge import Charge from deebot_client.commands.json.charge_state import GetChargeState -from deebot_client.commands.json.clean import CleanV2, GetCleanInfoV2 +from deebot_client.commands.json.clean import CleanAreaV2, CleanV2, GetCleanInfoV2 from deebot_client.commands.json.custom import CustomCommand from deebot_client.commands.json.error import GetError from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan @@ -81,7 +81,7 @@ def get_device_info() -> StaticDeviceInfo: battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), clean=CapabilityClean( - action=CapabilityCleanAction(command=CleanV2), + action=CapabilityCleanAction(command=CleanV2, area=CleanAreaV2), ), custom=CapabilityCustomCommand( event=CustomCommandEvent, get=[], set=CustomCommand