Skip to content

Commit 6ba5d91

Browse files
authored
Add XML Battery commands (#906)
1 parent 4c986ca commit 6ba5d91

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

deebot_client/commands/xml/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from deebot_client.command import Command, CommandMqttP2P
88

9+
from .battery import GetBatteryInfo
910
from .charge import Charge
1011
from .charge_state import GetChargeState
1112
from .error import GetError
@@ -20,6 +21,7 @@
2021

2122
__all__ = [
2223
"Charge",
24+
"GetBatteryInfo",
2325
"GetChargeState",
2426
"GetCleanSum",
2527
"GetError",
@@ -32,6 +34,7 @@
3234
# fmt: off
3335
# ordered by file asc
3436
_COMMANDS: list[type[XmlCommand]] = [
37+
GetBatteryInfo,
3538
GetError,
3639
GetLifeSpan,
3740
PlaySound,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Battery Info command."""
2+
3+
from __future__ import annotations
4+
5+
from typing import TYPE_CHECKING
6+
7+
from deebot_client.events import BatteryEvent
8+
from deebot_client.message import HandlingResult
9+
10+
from .common import XmlCommandWithMessageHandling
11+
12+
if TYPE_CHECKING:
13+
from xml.etree.ElementTree import Element
14+
15+
from deebot_client.event_bus import EventBus
16+
17+
18+
class GetBatteryInfo(XmlCommandWithMessageHandling):
19+
"""GetBatteryInfo command."""
20+
21+
NAME = "GetBatteryInfo"
22+
23+
@classmethod
24+
def _handle_xml(cls, event_bus: EventBus, xml: Element) -> HandlingResult:
25+
"""Handle xml message and notify the correct event subscribers.
26+
27+
:return: A message response
28+
"""
29+
if (
30+
xml.attrib.get("ret") != "ok"
31+
or (battery := xml.find("battery")) is None
32+
or (power := battery.attrib.get("power")) is None
33+
):
34+
return HandlingResult.analyse()
35+
36+
if power.isdecimal() and (power_int := int(power)) >= 0:
37+
event_bus.notify(BatteryEvent(power_int))
38+
return HandlingResult.success()
39+
40+
return HandlingResult.analyse()

tests/commands/xml/test_battery.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
import pytest
6+
7+
from deebot_client.command import CommandResult
8+
from deebot_client.commands.xml import GetBatteryInfo
9+
from deebot_client.events import BatteryEvent
10+
from deebot_client.message import HandlingState
11+
from tests.commands import assert_command
12+
13+
from . import get_request_xml
14+
15+
if TYPE_CHECKING:
16+
from deebot_client.events.base import Event
17+
18+
19+
@pytest.mark.parametrize(
20+
("power", "expected_event"),
21+
[
22+
(40, BatteryEvent(40)),
23+
],
24+
ids=["40_pct_battery"],
25+
)
26+
async def test_get_battery_info(power: int, expected_event: Event) -> None:
27+
xml_message = get_request_xml(f"<ctl ret='ok'><battery power='{power}' /></ctl>")
28+
await assert_command(GetBatteryInfo(), xml_message, expected_event)
29+
30+
31+
@pytest.mark.parametrize(
32+
"payload",
33+
[
34+
'<ctl ret="error"/>',
35+
'<ctl ret="ok"></ctl>',
36+
'<ctl ret="ok"><battery /></ctl>',
37+
'<ctl ret="ok"><test power="1" /></ctl>',
38+
'<ctl ret="ok"><battery power="-1" /></ctl>',
39+
'<ctl ret="ok"><battery power="test" /></ctl>',
40+
],
41+
ids=[
42+
"error",
43+
"no_state",
44+
"no_power",
45+
"wrong_inner_element",
46+
"negative_power",
47+
"strange_power_reading",
48+
],
49+
)
50+
async def test_get_battery_info_error(payload: str) -> None:
51+
xml_message = get_request_xml(payload)
52+
await assert_command(
53+
GetBatteryInfo(),
54+
xml_message,
55+
None,
56+
command_result=CommandResult(HandlingState.ANALYSE_LOGGED),
57+
)

0 commit comments

Comments
 (0)