Repository: DeebotUniverse/client.py
Pull request #898: Add minor map to map capabilities
Author: login: nanomad
Labels: name: pr: Breaking Change
description: Pull request with braking changes
Created: 2025-04-19T12:37:22Z | Merged: 2025-04-27T21:44:23Z

This is preparation for XML bots having map support


Diff:
diff --git a/deebot_client/capabilities.py b/deebot_client/capabilities.py
index d96aa7148..1181ed45d 100644
--- a/deebot_client/capabilities.py
+++ b/deebot_client/capabilities.py
@@ -174,6 +174,7 @@ class CapabilityMap:
     changed: CapabilityEvent[MapChangedEvent]
     clear: CapabilityExecute[[]] | None = None
     major: CapabilityEvent[MajorMapEvent]
+    minor: CapabilityExecute[[str, int]]
     multi_state: CapabilitySetEnable[MultimapStateEvent]
     position: CapabilityEvent[PositionsEvent]
     relocation: CapabilityExecute[[]]
diff --git a/deebot_client/commands/json/map.py b/deebot_client/commands/json/map.py
index 259980ddb..8aba84596 100644
--- a/deebot_client/commands/json/map.py
+++ b/deebot_client/commands/json/map.py
@@ -389,7 +389,7 @@ class GetMinorMap(JsonCommandWithMessageHandling, MessageBodyDataDict):
 
     NAME = "getMinorMap"
 
-    def __init__(self, *, map_id: str, piece_index: int) -> None:
+    def __init__(self, map_id: str, piece_index: int) -> None:
         super().__init__({"mid": map_id, "type": "ol", "pieceIndex": piece_index})
 
     @classmethod
diff --git a/deebot_client/device.py b/deebot_client/device.py
index 0b2838e7c..e07d38dd5 100644
--- a/deebot_client/device.py
+++ b/deebot_client/device.py
@@ -38,7 +38,6 @@
 _LOGGER = get_logger(__name__)
 _AVAILABLE_CHECK_INTERVAL = 60
 
-
 DeviceCommandExecute = Callable[[Command], Coroutine[Any, Any, dict[str, Any]]]
 
 
@@ -67,7 +66,11 @@ def __init__(
             self.execute_command, self.capabilities.get_refresh_commands
         )
 
-        self.map: Final[Map] = Map(self.execute_command, self.events)
+        self.map: Final[Map | None] = (
+            Map(self.execute_command, self.events, self.capabilities.map)
+            if self.capabilities.map
+            else None
+        )
 
         async def on_pos(event: PositionsEvent) -> None:
             if self._state == StateEvent(State.DOCKED):
@@ -141,7 +144,8 @@ async def teardown(self) -> None:
                 await self._available_task
 
         await self.events.teardown()
-        await self.map.teardown()
+        if self.map:
+            await self.map.teardown()
 
     async def _available_task_worker(self) -> None:
         while True:
diff --git a/deebot_client/hardware/deebot/2o4lnm.py b/deebot_client/hardware/deebot/2o4lnm.py
index 7b6cf7d89..c047b5552 100644
--- a/deebot_client/hardware/deebot/2o4lnm.py
+++ b/deebot_client/hardware/deebot/2o4lnm.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -162,6 +167,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/4bdkrs.py b/deebot_client/hardware/deebot/4bdkrs.py
index e450a4d2e..d46501570 100644
--- a/deebot_client/hardware/deebot/4bdkrs.py
+++ b/deebot_client/hardware/deebot/4bdkrs.py
@@ -49,7 +49,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -192,6 +197,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/7bryc5.py b/deebot_client/hardware/deebot/7bryc5.py
index 5a48adb27..20f9646ac 100644
--- a/deebot_client/hardware/deebot/7bryc5.py
+++ b/deebot_client/hardware/deebot/7bryc5.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/8kwdb4.py b/deebot_client/hardware/deebot/8kwdb4.py
index f54bc6fac..9b79374a3 100644
--- a/deebot_client/hardware/deebot/8kwdb4.py
+++ b/deebot_client/hardware/deebot/8kwdb4.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/9s1s80.py b/deebot_client/hardware/deebot/9s1s80.py
index d52105b82..922e1cb15 100644
--- a/deebot_client/hardware/deebot/9s1s80.py
+++ b/deebot_client/hardware/deebot/9s1s80.py
@@ -46,6 +46,7 @@
     GetCachedMapInfo,
     GetMajorMap,
     GetMapTrace,
+    GetMinorMap,
 )
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
@@ -168,6 +169,7 @@
             ),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/b2jqs4.py b/deebot_client/hardware/deebot/b2jqs4.py
index 81a6ccde7..5f8c0bba5 100644
--- a/deebot_client/hardware/deebot/b2jqs4.py
+++ b/deebot_client/hardware/deebot/b2jqs4.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/buom7k.py b/deebot_client/hardware/deebot/buom7k.py
index 790810f96..7687f949c 100644
--- a/deebot_client/hardware/deebot/buom7k.py
+++ b/deebot_client/hardware/deebot/buom7k.py
@@ -43,7 +43,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -156,6 +161,7 @@
             ),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/e6ofmn.py b/deebot_client/hardware/deebot/e6ofmn.py
index b4bab8416..acdf90c63 100644
--- a/deebot_client/hardware/deebot/e6ofmn.py
+++ b/deebot_client/hardware/deebot/e6ofmn.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -176,6 +181,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/ee23uv.py b/deebot_client/hardware/deebot/ee23uv.py
index e450a4d2e..d46501570 100644
--- a/deebot_client/hardware/deebot/ee23uv.py
+++ b/deebot_client/hardware/deebot/ee23uv.py
@@ -49,7 +49,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -192,6 +197,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/kr0277.py b/deebot_client/hardware/deebot/kr0277.py
index 2fd89843e..da39035e2 100644
--- a/deebot_client/hardware/deebot/kr0277.py
+++ b/deebot_client/hardware/deebot/kr0277.py
@@ -38,7 +38,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -147,6 +152,7 @@
             ),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/m1wkuw.py b/deebot_client/hardware/deebot/m1wkuw.py
index 33a1c5337..bf12fe72f 100644
--- a/deebot_client/hardware/deebot/m1wkuw.py
+++ b/deebot_client/hardware/deebot/m1wkuw.py
@@ -46,6 +46,7 @@
     GetCachedMapInfo,
     GetMajorMap,
     GetMapTrace,
+    GetMinorMap,
 )
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
@@ -162,6 +163,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/p1jij8.py b/deebot_client/hardware/deebot/p1jij8.py
index 4a8cf74e9..cdd410565 100644
--- a/deebot_client/hardware/deebot/p1jij8.py
+++ b/deebot_client/hardware/deebot/p1jij8.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/p7l7iu.py b/deebot_client/hardware/deebot/p7l7iu.py
index 17fd7eb7d..1f10011e7 100644
--- a/deebot_client/hardware/deebot/p7l7iu.py
+++ b/deebot_client/hardware/deebot/p7l7iu.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -176,6 +181,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/p95mgv.py b/deebot_client/hardware/deebot/p95mgv.py
index 3f2293619..639e8870e 100644
--- a/deebot_client/hardware/deebot/p95mgv.py
+++ b/deebot_client/hardware/deebot/p95mgv.py
@@ -51,6 +51,7 @@
     GetCachedMapInfo,
     GetMajorMap,
     GetMapTrace,
+    GetMinorMap,
 )
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
@@ -174,6 +175,7 @@
             ),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/qhe2o2.py b/deebot_client/hardware/deebot/qhe2o2.py
index 87d569905..bb66a41f5 100644
--- a/deebot_client/hardware/deebot/qhe2o2.py
+++ b/deebot_client/hardware/deebot/qhe2o2.py
@@ -43,7 +43,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -156,6 +161,7 @@
             ),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/ue8kcc.py b/deebot_client/hardware/deebot/ue8kcc.py
index e450a4d2e..d46501570 100644
--- a/deebot_client/hardware/deebot/ue8kcc.py
+++ b/deebot_client/hardware/deebot/ue8kcc.py
@@ -49,7 +49,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -192,6 +197,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/umwv6z.py b/deebot_client/hardware/deebot/umwv6z.py
index aaedcc0cb..9daa11c0e 100644
--- a/deebot_client/hardware/deebot/umwv6z.py
+++ b/deebot_client/hardware/deebot/umwv6z.py
@@ -46,6 +46,7 @@
     GetCachedMapInfo,
     GetMajorMap,
     GetMapTrace,
+    GetMinorMap,
 )
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
@@ -164,6 +165,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/x5d34r.py b/deebot_client/hardware/deebot/x5d34r.py
index 88abc643a..0b24c442d 100644
--- a/deebot_client/hardware/deebot/x5d34r.py
+++ b/deebot_client/hardware/deebot/x5d34r.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/xco2fc.py b/deebot_client/hardware/deebot/xco2fc.py
index 1856f0db0..f9574d7bb 100644
--- a/deebot_client/hardware/deebot/xco2fc.py
+++ b/deebot_client/hardware/deebot/xco2fc.py
@@ -42,7 +42,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -153,6 +158,7 @@
             cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
             changed=CapabilityEvent(MapChangedEvent, []),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/hardware/deebot/yna5xi.py b/deebot_client/hardware/deebot/yna5xi.py
index 37a63e860..c77eb6feb 100644
--- a/deebot_client/hardware/deebot/yna5xi.py
+++ b/deebot_client/hardware/deebot/yna5xi.py
@@ -38,7 +38,12 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
+    GetCachedMapInfo,
+    GetMajorMap,
+    GetMapTrace,
+    GetMinorMap,
+)
 from deebot_client.commands.json.multimap_state import (
     GetMultimapState,
     SetMultimapState,
@@ -130,6 +135,7 @@
             changed=CapabilityEvent(MapChangedEvent, []),
             clear=CapabilityExecute(ClearMap),
             major=CapabilityEvent(MajorMapEvent, [GetMajorMap()]),
+            minor=CapabilityExecute(GetMinorMap),
             multi_state=CapabilitySetEnable(
                 MultimapStateEvent, [GetMultimapState()], SetMultimapState
             ),
diff --git a/deebot_client/map.py b/deebot_client/map.py
index c6afe8348..52dad3a26 100644
--- a/deebot_client/map.py
+++ b/deebot_client/map.py
@@ -8,7 +8,6 @@
 
 from deebot_client.events.map import CachedMapInfoEvent, MapChangedEvent
 
-from .commands.json import GetMinorMap
 from .events import (
     MajorMapEvent,
     MapSetEvent,
@@ -31,10 +30,10 @@
 if TYPE_CHECKING:
     from collections.abc import Callable
 
+    from .capabilities import CapabilityMap
     from .device import DeviceCommandExecute
     from .event_bus import EventBus
 
-
 _LOGGER = get_logger(__name__)
 
 
@@ -45,10 +44,12 @@ def __init__(
         self,
         execute_command: DeviceCommandExecute,
         event_bus: EventBus,
+        capabilities: CapabilityMap,
     ) -> None:
         self._execute_command = execute_command
         self._event_bus = event_bus
 
+        self._capabilities = capabilities
         self._map_data: Final[MapData] = MapData(event_bus)
         self._amount_rooms: int = 0
         self._last_image: str | None = None
@@ -104,7 +105,7 @@ async def on_major_map(event: MajorMapEvent) -> None:
                     ):
                         tg.create_task(
                             self._execute_command(
-                                GetMinorMap(map_id=event.map_id, piece_index=idx)
+                                self._capabilities.minor.execute(event.map_id, idx)
                             )
                         )
 
diff --git a/tests/conftest.py b/tests/conftest.py
index dd41b1b9f..acd6d7663 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -129,6 +129,7 @@ async def test_mqtt_client(
 async def static_device_info() -> StaticDeviceInfo:
     info = await get_static_device_info("yna5xi")
     assert info is not None
+    assert info.capabilities.map is not None
     return info
 
 
diff --git a/tests/test_device.py b/tests/test_device.py
index 1362e0d12..f34be3de3 100644
--- a/tests/test_device.py
+++ b/tests/test_device.py
@@ -6,12 +6,15 @@
 from typing import TYPE_CHECKING
 from unittest.mock import Mock, patch
 
+import pytest
+
 from deebot_client.command import DeviceCommandResult
 from deebot_client.commands.json.battery import GetBattery
 from deebot_client.device import Device
 from deebot_client.events import AvailabilityEvent
 from deebot_client.events.network import NetworkInfoEvent
-from deebot_client.models import DeviceInfo
+from deebot_client.hardware import get_static_device_info
+from deebot_client.models import DeviceInfo, StaticDeviceInfo
 from deebot_client.mqtt_client import MqttClient, SubscriberInfo
 from tests.helpers import mock_static_device_info
 from tests.helpers.tasks import block_till_done
@@ -133,3 +136,27 @@ async def test_mac_address(
 
     assert device.mac == mac
     await device.teardown()
+
+
+def static_device_info_no_map() -> StaticDeviceInfo:
+    """Return a StaticDeviceInfo without map capability."""
+    info = asyncio.run(get_static_device_info("2ap5uq"))
+    assert info is not None
+    assert info.capabilities.map is None
+    return info
+
+
+@pytest.mark.parametrize(
+    "static_device_info",
+    [
+        static_device_info_no_map(),
+    ],
+)
+async def test_behaviour_with_no_map_capability(
+    authenticator: Authenticator, device_info: DeviceInfo
+) -> None:
+    device = Device(device_info, authenticator)
+
+    assert device.map is None
+
+    await device.teardown()
diff --git a/tests/test_map.py b/tests/test_map.py
index 0ec7889f6..4ef7c357d 100644
--- a/tests/test_map.py
+++ b/tests/test_map.py
@@ -22,7 +22,7 @@
     Map,
     MapData,
 )
-from deebot_client.models import Room
+from deebot_client.models import Room, StaticDeviceInfo
 from deebot_client.rs.map import PositionType
 
 from .common import block_till_done
@@ -83,9 +83,12 @@ async def test_Map_subscriptions(
     event_bus: EventBus,
     prepare_fn: Callable[[Mock], None],
     events_with_subscriber: list[type[Event]],
+    static_device_info: StaticDeviceInfo,
 ) -> None:
     prepare_fn(event_bus_mock)
-    map = Map(execute_mock, event_bus_mock)
+    capabilities_map = static_device_info.capabilities.map
+    assert capabilities_map is not None
+    map = Map(execute_mock, event_bus_mock, capabilities_map)
 
     calls = [call(MapSetEvent, ANY), call(MapSubsetEvent, ANY)]
     event_bus_mock.subscribe.assert_has_calls(calls)
@@ -126,11 +129,15 @@ async def on_change() -> None:
     assert not map._unsubscribers
 
 
-async def setup_map(execute_mock: AsyncMock, event_bus: EventBus) -> Map:
+async def setup_map(
+    execute_mock: AsyncMock, event_bus: EventBus, static_device_info: StaticDeviceInfo
+) -> Map:
     async def on_change(_: MapChangedEvent) -> None:
         pass
 
-    map = Map(execute_mock, event_bus)
+    capabilities_map = static_device_info.capabilities.map
+    assert capabilities_map is not None
+    map = Map(execute_mock, event_bus, capabilities_map)
     event_bus.subscribe(MapChangedEvent, on_change)
     await block_till_done(event_bus)
     return map
@@ -156,9 +163,10 @@ async def test_invalid_map_piece_index(
     event_bus: EventBus,
     event: Event,
     exception_class: type[Exception],
+    static_device_info: StaticDeviceInfo,
 ) -> None:
     """Test invalid map piece index."""
-    await setup_map(execute_mock, event_bus)
+    await setup_map(execute_mock, event_bus, static_device_info)
 
     event_bus.notify(event)
     with pytest.raises(exception_class) as ex:
@@ -173,9 +181,10 @@ async def test_invalid_map_piece_index(
 async def test_get_svg_map_empty(
     execute_mock: AsyncMock,
     event_bus: EventBus,
+    static_device_info: StaticDeviceInfo,
 ) -> None:
     """Test getting svg map without data returns None."""
-    map = await setup_map(execute_mock, event_bus)
+    map = await setup_map(execute_mock, event_bus, static_device_info)
     assert map.get_svg_map() is None
 
 
@@ -184,11 +193,12 @@ def test_get_svg_map(
     benchmark: BenchmarkFixture,
     execute_mock: AsyncMock,
     event_bus: EventBus,
+    static_device_info: StaticDeviceInfo,
 ) -> None:
     """Test getting svg map."""
 
     async def test_fn() -> str | None:
-        map = await setup_map(execute_mock, event_bus)
+        map = await setup_map(execute_mock, event_bus, static_device_info)
 
         for event in _events_for_map_test():
             event_bus.notify(event)


Reviews:
user: login: edenhaus
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-19T17:57:05Z
user: login: edenhaus
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-22T21:43:42Z
user: login: edenhaus
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-22T21:43:58Z
user: login: edenhaus
body: Please implement my requested changes. If you think there is a better approach than comment on the comment but don't resolve it without implementing the requested changes or any comment on it
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-22T21:45:04Z
user: login: nanomad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:07:47Z
user: login: nanomad
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:07:59Z
user: login: edenhaus
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-27T18:59:26Z
user: login: edenhaus
body: Thanks @nanomad :+1: 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-27T21:44:16Z

Review comments:
diff_hunk: @@ -164,17 +160,26 @@
         ),
         map=CapabilityMap(
             cached_info=CapabilityEvent(
-                CachedMapInfoEvent, [GetCachedMapInfo(version=2)]
+                CachedMapInfoEvent,
+                [deebot_client.commands.json.map.GetCachedMapInfo(version=2)],
path: deebot_client/hardware/deebot/9s1s80.py
user: login: edenhaus
body: Please revert all unrelated changes and import the Commands instead of the module
created_at: 2025-04-19T17:26:23Z
author_association: MEMBER
diff_hunk: @@ -27,7 +27,11 @@
 from deebot_client.commands.json.error import GetError
 from deebot_client.commands.json.fan_speed import GetFanSpeed
 from deebot_client.commands.json.life_span import GetLifeSpan
-from deebot_client.commands.json.map import GetCachedMapInfo, GetMajorMap, GetMapTrace
+from deebot_client.commands.json.map import (
path: tests/hardware/test_init.py
user: login: edenhaus
body: Revert this changes
created_at: 2025-04-19T17:28:03Z
author_association: MEMBER
diff_hunk: @@ -45,10 +44,14 @@ def __init__(
         self,
         execute_command: DeviceCommandExecute,
         event_bus: EventBus,
+        minor_map_command: Callable[[str, int], Command] | None,
path: deebot_client/map.py
user: login: edenhaus
body: ```suggestion
        capabilities: CapabilityMap,
```
created_at: 2025-04-19T17:30:46Z
author_association: MEMBER
diff_hunk: @@ -45,10 +44,14 @@ def __init__(
         self,
         execute_command: DeviceCommandExecute,
         event_bus: EventBus,
+        minor_map_command: Callable[[str, int], Command] | None,
     ) -> None:
         self._execute_command = execute_command
         self._event_bus = event_bus
 
+        self._minor_map_command: Callable[[str, int], Command] | None = (
+            minor_map_command
+        )
path: deebot_client/map.py
user: login: edenhaus
body: ```suggestion
        self._capabilities = capabilities
```
created_at: 2025-04-19T17:53:52Z
author_association: MEMBER
diff_hunk: @@ -101,10 +104,11 @@ async def on_major_map(event: MajorMapEvent) -> None:
                     if (
                         self._map_data.map_piece_crc32_indicates_update(idx, value)
                         and event.requested
+                        and self._minor_map_command is not None
path: deebot_client/map.py
user: login: edenhaus
body: ```suggestion
```
created_at: 2025-04-19T17:53:59Z
author_association: MEMBER
diff_hunk: @@ -101,10 +104,11 @@ async def on_major_map(event: MajorMapEvent) -> None:
                     if (
                         self._map_data.map_piece_crc32_indicates_update(idx, value)
                         and event.requested
+                        and self._minor_map_command is not None
                     ):
                         tg.create_task(
                             self._execute_command(
-                                GetMinorMap(map_id=event.map_id, piece_index=idx)
+                                self._minor_map_command(event.map_id, idx)
path: deebot_client/map.py
user: login: edenhaus
body: ```suggestion
                                self._capabilities.minor.execute(event.map_id, idx)
```
created_at: 2025-04-19T17:54:24Z
author_association: MEMBER
diff_hunk: @@ -67,7 +66,13 @@ def __init__(
             self.execute_command, self.capabilities.get_refresh_commands
         )
 
-        self.map: Final[Map] = Map(self.execute_command, self.events)
+        self.map: Final[Map] = Map(
+            self.execute_command,
+            self.events,
+            self.capabilities.map.minor.execute
+            if self.capabilities and self.capabilities.map
+            else None,
+        )
path: deebot_client/device.py
user: login: edenhaus
body: ```suggestion
        self.map: Final[Map | None] = (
            Map(self.execute_command, self.events, self.capabilities.map)
            if self.capabilities.map
            else None
        )
```
created_at: 2025-04-19T17:55:18Z
author_association: MEMBER
diff_hunk: @@ -45,10 +44,14 @@ def __init__(
         self,
         execute_command: DeviceCommandExecute,
         event_bus: EventBus,
+        minor_map_command: Callable[[str, int], Command] | None,
path: deebot_client/map.py
user: login: edenhaus
body: Please implemented my requested changes
created_at: 2025-04-22T21:43:42Z
author_association: MEMBER
diff_hunk: @@ -67,7 +66,13 @@ def __init__(
             self.execute_command, self.capabilities.get_refresh_commands
         )
 
-        self.map: Final[Map] = Map(self.execute_command, self.events)
+        self.map: Final[Map] = Map(
+            self.execute_command,
+            self.events,
+            self.capabilities.map.minor.execute
+            if self.capabilities and self.capabilities.map
+            else None,
+        )
path: deebot_client/device.py
user: login: edenhaus
body: Same here
created_at: 2025-04-22T21:43:58Z
author_association: MEMBER
diff_hunk: @@ -45,10 +44,14 @@ def __init__(
         self,
         execute_command: DeviceCommandExecute,
         event_bus: EventBus,
+        minor_map_command: Callable[[str, int], Command] | None,
path: deebot_client/map.py
user: login: nanomad
body: Already done?
created_at: 2025-04-24T09:07:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -67,7 +66,13 @@ def __init__(
             self.execute_command, self.capabilities.get_refresh_commands
         )
 
-        self.map: Final[Map] = Map(self.execute_command, self.events)
+        self.map: Final[Map] = Map(
+            self.execute_command,
+            self.events,
+            self.capabilities.map.minor.execute
+            if self.capabilities and self.capabilities.map
+            else None,
+        )
path: deebot_client/device.py
user: login: nanomad
body: Done as well :)
created_at: 2025-04-24T09:07:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -157,6 +166,17 @@ def device_info(
     )
 
 
+@pytest.fixture
+def device_info_no_map(
+    api_device_info: ApiDeviceInfo,
+    static_device_info_no_map: StaticDeviceInfo,
+) -> DeviceInfo:
+    return DeviceInfo(
+        api_device_info,
+        static_device_info_no_map,
+    )
+
+
path: tests/conftest.py
user: login: edenhaus
body: ```suggestion
```

Not needed as we can overwrite the `static_device_info` fixture if needed
created_at: 2025-04-27T18:50:47Z
author_association: MEMBER
diff_hunk: @@ -129,6 +129,15 @@ async def test_mqtt_client(
 async def static_device_info() -> StaticDeviceInfo:
     info = await get_static_device_info("yna5xi")
     assert info is not None
+    assert info.capabilities.map is not None
+    return info
+
+
+@pytest.fixture
+async def static_device_info_no_map() -> StaticDeviceInfo:
+    info = await get_static_device_info("2ap5uq")
+    assert info is not None
+    assert info.capabilities.map is None
path: tests/conftest.py
user: login: edenhaus
body: ```suggestion
```

Not needed here if used only by one test
created_at: 2025-04-27T18:57:40Z
author_association: MEMBER
diff_hunk: @@ -133,3 +133,15 @@ async def test_mac_address(
 
     assert device.mac == mac
     await device.teardown()
+
+
+async def test_behaviour_with_no_map_capability(
+    authenticator: Authenticator, device_info_no_map: DeviceInfo
+) -> None:
+    device = Device(device_info_no_map, authenticator)
path: tests/test_device.py
user: login: edenhaus
body: ```suggestion
def static_device_info_no_map() -> StaticDeviceInfo:
    """Return a StaticDeviceInfo without map capability."""
    info = asyncio.run(get_static_device_info("2ap5uq"))
    assert info is not None
    assert info.capabilities.map is None
    return info


@pytest.mark.parametrize(
    "static_device_info",
    [
        static_device_info_no_map(),
    ],
)
async def test_behaviour_with_no_map_capability(
    authenticator: Authenticator, device_info: DeviceInfo
) -> None:
    device = Device(device_info, authenticator)
```
created_at: 2025-04-27T18:58:47Z
author_association: MEMBER
diff_hunk: @@ -133,3 +133,15 @@ async def test_mac_address(
 
     assert device.mac == mac
     await device.teardown()
+
+
+async def test_behaviour_with_no_map_capability(
+    authenticator: Authenticator, device_info_no_map: DeviceInfo
+) -> None:
+    device = Device(device_info_no_map, authenticator)
+    # deactivate refresh event subscribe refresh calls
+    device.events._get_refresh_commands = lambda _: []
path: tests/test_device.py
user: login: edenhaus
body: Why?
created_at: 2025-04-27T18:59:08Z
author_association: MEMBER

PR comments:
user: login: codecov[bot]
created_at: 2025-04-19T12:40:19Z
body: ## [Codecov](https://app.codecov.io/gh/DeebotUniverse/client.py/pull/898?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DeebotUniverse) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 92.78%. Comparing base [(`1465b5c`)](https://app.codecov.io/gh/DeebotUniverse/client.py/commit/1465b5c1875cefee5f7946d620f2fc425af21828?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DeebotUniverse) to head [(`78db1f6`)](https://app.codecov.io/gh/DeebotUniverse/client.py/commit/78db1f678c7e547533bd4d40815cea8ae27c0768?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DeebotUniverse).
> Report is 1 commits behind head on dev.

:white_check_mark: All tests successful. No failed tests found.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##              dev     #898   +/-   ##
=======================================
  Coverage   92.78%   92.78%           
=======================================
  Files         125      125           
  Lines        4824     4826    +2     
  Branches      309      310    +1     
=======================================
+ Hits         4476     4478    +2     
  Misses        285      285           
  Partials       63       63           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/DeebotUniverse/client.py/pull/898?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DeebotUniverse).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DeebotUniverse).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: codspeed-hq[bot]
created_at: 2025-04-19T12:46:22Z
body: <!-- __CODSPEED_PERFORMANCE_REPORT_COMMENT__ -->
<!-- __CODSPEED_INSTRUMENTATION_PERFORMANCE_REPORT_COMMENT__ -->

## [CodSpeed Performance Report](https://codspeed.io/DeebotUniverse/client.py/branches/nanomad%3Afeature%2Fminor-map-capability)

### Merging #898 will **not alter performance**

<sub>Comparing <code>nanomad:feature/minor-map-capability</code> (78db1f6) with <code>dev</code> (1465b5c)</sub>



### Summary

`✅ 6` untouched benchmarks  




author_association: NONE
user: login: nanomad
created_at: 2025-04-22T21:45:15Z
body: I think I've missed a push after the rebase, I'll take a look at it
tomorrow

Il Mar 22 Apr 2025, 23:44 Robert Resch ***@***.***> ha
scritto:

> ***@***.**** commented on this pull request.
> ------------------------------
>
> In deebot_client/device.py
> <https://github.com/DeebotUniverse/client.py/pull/898#discussion_r2054928822>
> :
>
> > +        self.map: Final[Map] = Map(
> +            self.execute_command,
> +            self.events,
> +            self.capabilities.map.minor.execute
> +            if self.capabilities and self.capabilities.map
> +            else None,
> +        )
>
> Same here
>
> —
> Reply to this email directly, view it on GitHub
> <https://github.com/DeebotUniverse/client.py/pull/898#discussion_r2054928822>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAIT3RV75MA5B224VDBS2TT222Z3HAVCNFSM6AAAAAB3OQ25GWVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDOOBVGQ2TGNRUGI>
> .
> You are receiving this because you authored the thread.Message ID:
> ***@***.***>
>

author_association: CONTRIBUTOR
user: login: nanomad
created_at: 2025-04-22T21:50:32Z
body: > Please implement my requested changes. If you think there is a better approach than comment on the comment but don't resolve it without implementing the requested changes or any comment on it

Uhm, I'm looking at the code in the "files" section and I do see your changes integrated. I think github is potentially showing you outdated info?
author_association: CONTRIBUTOR
user: login: edenhaus
created_at: 2025-04-27T15:33:36Z
body: > Uhm, I'm looking at the code in the "files" section and I do see your changes integrated. I think github is potentially showing you outdated info?

![grafik](https://github.com/user-attachments/assets/91d7f5c1-3e66-4fcc-a3ab-403e20dc3169)
I see this and here my requested changes are missing. I also checked out the code local and there also my requested changes are missing. Are you sure you have pushed all changes?
author_association: MEMBER
user: login: nanomad
created_at: 2025-04-27T15:46:47Z
body: @edenhaus I do now see what you mean. I'll rework this PR as making map nullable requires other changes as well
author_association: CONTRIBUTOR
user: login: nanomad
created_at: 2025-04-27T16:21:29Z
body: @edenhaus Done, I guess this is a breaking change since
- We've added a new mandatory capability (low impact since this PR takes care of migrating existing bots as well)
- The map attribute of the device can now be None (instead of simply not working for bots such as 2ap5uq)
author_association: CONTRIBUTOR