Skip to content

Commit 83c5bbc

Browse files
authored
Implement XML Map messages (#929)
1 parent 64fb815 commit 83c5bbc

3 files changed

Lines changed: 124 additions & 1 deletion

File tree

deebot_client/messages/xml/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,25 @@
66

77
from deebot_client.messages.xml.battery import BatteryInfo
88
from deebot_client.messages.xml.charge_state import ChargeState
9+
from deebot_client.messages.xml.map import MapP, Trace
910
from deebot_client.messages.xml.pos import Pos
1011

1112
if TYPE_CHECKING:
1213
from collections.abc import Sequence
1314

1415
from deebot_client.message import Message
1516

16-
__all__: Sequence[str] = ["BatteryInfo", "ChargeState", "Pos"]
17+
__all__: Sequence[str] = ["BatteryInfo", "ChargeState", "MapP", "Pos", "Trace"]
1718
# fmt: off
1819
# ordered by file asc
1920
_MESSAGES: list[type[Message]] = [
2021
BatteryInfo,
2122

2223
ChargeState,
2324

25+
MapP,
26+
Trace,
27+
2428
Pos
2529
]
2630
# fmt: on

deebot_client/messages/xml/map.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""Map messages."""
2+
3+
from __future__ import annotations
4+
5+
from typing import TYPE_CHECKING
6+
7+
from deebot_client.events.map import MapTraceEvent, MinorMapEvent
8+
from deebot_client.message import HandlingResult
9+
from deebot_client.messages.xml.common import XmlMessage
10+
11+
if TYPE_CHECKING:
12+
from xml.etree.ElementTree import Element
13+
14+
from deebot_client.event_bus import EventBus
15+
16+
17+
class MapP(XmlMessage):
18+
"""MapP message."""
19+
20+
NAME = "MapP"
21+
22+
@classmethod
23+
def _handle_xml(cls, event_bus: EventBus, xml: Element) -> HandlingResult:
24+
"""Handle xml message and notify the correct event subscribers.
25+
26+
Sample message:
27+
b"<ctl td='MapP' i='1245233875' pid='27' p='XQAABAAQJwAAAABv/f//o7f/Rz5IFXI5YVG4kYRDU5g6Z4W8UflplyVyfWyHmYdt2YVgA/k3ENxVye1lEM...fqEp3pept9Re5qT0lZFDWpoFg4D51VXQopPSDLSo2ZpM/zQ4IAhvgWIKnp7zlwcd6Ekj7U2FnOTTAQeWq3DPT+MTrAVO2wL/6mmGODzk4hBtA/wjZzOujPgEA=='/>"
28+
:return: A message response
29+
"""
30+
if (
31+
(pid := xml.attrib.get("pid"))
32+
and (piece := xml.attrib.get("p"))
33+
and pid.isdecimal()
34+
):
35+
event_bus.notify(MinorMapEvent(index=int(pid), value=piece))
36+
return HandlingResult.success()
37+
38+
return HandlingResult.analyse()
39+
40+
41+
class Trace(XmlMessage):
42+
"""Trace message."""
43+
44+
NAME = "trace"
45+
46+
@classmethod
47+
def _handle_xml(cls, event_bus: EventBus, xml: Element) -> HandlingResult:
48+
"""Handle xml message and notify the correct event subscribers.
49+
50+
Sample message:
51+
<ctl td='trace' trid='631369' tf='16' tt='17' tr='XQAABAAKAAAAAG0/wEAAA2cAS5AAAA=='/>
52+
:return: A message response
53+
"""
54+
if (
55+
(tf := xml.attrib.get("tf"))
56+
and tf.isdecimal()
57+
and (tt := xml.attrib.get("tt"))
58+
and tt.isdecimal()
59+
and (tr := xml.attrib.get("tr"))
60+
):
61+
event_bus.notify(MapTraceEvent(start=int(tf), total=int(tt), data=tr))
62+
return HandlingResult.success()
63+
return HandlingResult.analyse()

tests/messages/xml/test_map.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from deebot_client.events import MapTraceEvent, MinorMapEvent
6+
from deebot_client.message import HandlingState
7+
from deebot_client.messages.xml import MapP, Trace
8+
from tests.messages import assert_message, assert_message_failure
9+
10+
11+
@pytest.mark.parametrize(("pid", "data"), [(42, "base64data")])
12+
def test_MapP(pid: int, data: str) -> None:
13+
xml_message = f"<ctl td='MapP' i='1245233875' pid='{pid}' p='{data}'/>"
14+
assert_message(
15+
MapP,
16+
xml_message,
17+
MinorMapEvent(index=pid, value=data),
18+
)
19+
20+
21+
@pytest.mark.parametrize(
22+
"xml_message",
23+
{
24+
"<ctl td='MapP' i='1245233875' pid='XXX' p='base64data'/>",
25+
"<ctl td='MapP' i='1245233875' p='base64data'/>",
26+
"<ctl td='MapP' i='1245233875' pid='42' />",
27+
"<ctl td='MapP' i='1245233875' />",
28+
},
29+
)
30+
def test_MapP_error(xml_message: str) -> None:
31+
assert_message_failure(MapP, xml_message, HandlingState.ANALYSE_LOGGED)
32+
33+
34+
@pytest.mark.parametrize(("tf", "tt", "tr"), [(13, 42, "base64data")])
35+
def test_Trace(tf: int, tt: int, tr: str) -> None:
36+
xml_message = f"<ctl td='trace' trid='631369' tf='{tf}' tt='{tt}' tr='{tr}'/>"
37+
assert_message(
38+
Trace,
39+
xml_message,
40+
MapTraceEvent(start=tf, total=tt, data=tr),
41+
)
42+
43+
44+
@pytest.mark.parametrize(
45+
"xml_message",
46+
{
47+
"<ctl td='trace' trid='631369' tt='17' tr='XQAABAAKAAAAAG0/wEAAA2cAS5AAAA=='/>",
48+
"<ctl td='trace' trid='631369' tf='XXX' tt='17' tr='XQAABAAKAAAAAG0/wEAAA2cAS5AAAA=='/>",
49+
"<ctl td='trace' trid='631369' tf='16' tr='XQAABAAKAAAAAG0/wEAAA2cAS5AAAA=='/>",
50+
"<ctl td='trace' trid='631369' tf='16' tt='XXX' tr='XQAABAAKAAAAAG0/wEAAA2cAS5AAAA=='/>",
51+
"<ctl td='trace' trid='631369' tf='16' tt='16' />",
52+
"<ctl td='trace' trid='631369' />",
53+
},
54+
)
55+
def test_Trace_error(xml_message: str) -> None:
56+
assert_message_failure(Trace, xml_message, HandlingState.ANALYSE_LOGGED)

0 commit comments

Comments
 (0)