diff --git a/deebot_client/capabilities.py b/deebot_client/capabilities.py index 84bd3652..6a93c765 100644 --- a/deebot_client/capabilities.py +++ b/deebot_client/capabilities.py @@ -11,7 +11,6 @@ from deebot_client.events import ( AdvancedModeEvent, AvailabilityEvent, - BaseStationEvent, BatteryEvent, BorderSwitchEvent, CachedMapInfoEvent, @@ -42,6 +41,7 @@ RoomsEvent, SafeProtectEvent, StateEvent, + StationEvent, StatsEvent, SweepModeEvent, TotalStatsEvent, @@ -61,7 +61,7 @@ from _typeshed import DataclassInstance from deebot_client.command import Command - from deebot_client.commands import BaseStationAction + from deebot_client.commands import StationAction from deebot_client.commands.json.common import ExecuteCommand from deebot_client.events.efficiency_mode import EfficiencyMode, EfficiencyModeEvent from deebot_client.models import CleanAction, CleanMode @@ -109,10 +109,10 @@ class CapabilitySetEnable(CapabilitySet[_EVENT, [bool]]): @dataclass(frozen=True) -class CapabilityExecute: +class CapabilityExecute(Generic[_P]): """Capability to execute a command.""" - execute: type[Command] + execute: Callable[_P, Command] @dataclass(frozen=True, kw_only=True) @@ -122,6 +122,11 @@ class CapabilityTypes(Generic[_T]): types: tuple[_T, ...] +@dataclass(frozen=True, kw_only=True) +class CapabilityExecuteTypes(CapabilityTypes[_T], CapabilityExecute[[_T]]): + """Capability to execute a command with types.""" + + @dataclass(frozen=True, kw_only=True) class CapabilitySetTypes(CapabilitySet[_EVENT, _P], CapabilityTypes[_T]): """Capability for set command and types.""" @@ -169,11 +174,11 @@ class CapabilityMap: cached_info: CapabilityEvent[CachedMapInfoEvent] changed: CapabilityEvent[MapChangedEvent] - clear: CapabilityExecute | None = None + clear: CapabilityExecute[[]] | None = None major: CapabilityEvent[MajorMapEvent] multi_state: CapabilitySetEnable[MultimapStateEvent] position: CapabilityEvent[PositionsEvent] - relocation: CapabilityExecute + relocation: CapabilityExecute[[]] rooms: CapabilityEvent[RoomsEvent] trace: CapabilityEvent[MapTraceEvent] @@ -216,13 +221,13 @@ class CapabilitySettings: class CapabilityBaseStation: """Capabilities for the base station.""" - action: Callable[[BaseStationAction], Command] + action: CapabilityExecuteTypes[StationAction] auto_empty: CapabilitySetTypes[ auto_empty.AutoEmptyEvent, [bool | None, auto_empty.Frequency | str | None], auto_empty.Frequency, ] - status: CapabilityEvent[BaseStationEvent] + state: CapabilityEvent[StationEvent] @dataclass(frozen=True, kw_only=True) @@ -234,7 +239,7 @@ class Capabilities(ABC): availability: CapabilityEvent[AvailabilityEvent] base_station: CapabilityBaseStation | None = None battery: CapabilityEvent[BatteryEvent] - charge: CapabilityExecute + charge: CapabilityExecute[[]] clean: CapabilityClean custom: CapabilityCustomCommand[CustomCommandEvent] error: CapabilityEvent[ErrorEvent] @@ -244,7 +249,7 @@ class Capabilities(ABC): life_span: CapabilityLifeSpan map: CapabilityMap | None = None network: CapabilityEvent[NetworkInfoEvent] - play_sound: CapabilityExecute + play_sound: CapabilityExecute[[]] settings: CapabilitySettings state: CapabilityEvent[StateEvent] stats: CapabilityStats diff --git a/deebot_client/commands/__init__.py b/deebot_client/commands/__init__.py index 90fd37db..5fb527c4 100644 --- a/deebot_client/commands/__init__.py +++ b/deebot_client/commands/__init__.py @@ -23,7 +23,7 @@ @unique -class BaseStationAction(IntEnum): - """Enum class for all possible base station actions.""" +class StationAction(IntEnum): + """Enum class for all possible station actions.""" EMPTY_DUSTBIN = 1 diff --git a/deebot_client/commands/json/station_action.py b/deebot_client/commands/json/station_action.py index 16330e24..0e78bb05 100644 --- a/deebot_client/commands/json/station_action.py +++ b/deebot_client/commands/json/station_action.py @@ -4,14 +4,10 @@ from typing import TYPE_CHECKING -from deebot_client.logging_filter import get_logger - from .common import ExecuteCommand if TYPE_CHECKING: - from deebot_client.commands import BaseStationAction - -_LOGGER = get_logger(__name__) + from deebot_client import commands class StationAction(ExecuteCommand): @@ -19,5 +15,5 @@ class StationAction(ExecuteCommand): NAME = "stationAction" - def __init__(self, action: BaseStationAction) -> None: + def __init__(self, action: commands.StationAction) -> None: super().__init__({"act": 1, "type": action.value}) diff --git a/deebot_client/events/__init__.py b/deebot_client/events/__init__.py index 403fa332..74d636f6 100644 --- a/deebot_client/events/__init__.py +++ b/deebot_client/events/__init__.py @@ -8,9 +8,8 @@ from deebot_client.events.base import Event -from . import auto_empty, base_station +from . import auto_empty, station from .auto_empty import AutoEmptyEvent -from .base_station import BaseStationEvent from .efficiency_mode import EfficiencyMode, EfficiencyModeEvent from .fan_speed import FanSpeedEvent, FanSpeedLevel from .map import ( @@ -27,6 +26,7 @@ PositionType, ) from .network import NetworkInfoEvent +from .station import StationEvent from .water_info import SweepType, WaterAmount, WaterInfoEvent from .work_mode import WorkMode, WorkModeEvent @@ -35,7 +35,6 @@ __all__ = [ "AutoEmptyEvent", - "BaseStationEvent", "BatteryEvent", "CachedMapInfoEvent", "CleanJobStatus", @@ -56,6 +55,7 @@ "Position", "PositionType", "PositionsEvent", + "StationEvent", "SweepModeEvent", "SweepType", "WaterAmount", @@ -63,7 +63,7 @@ "WorkMode", "WorkModeEvent", "auto_empty", - "base_station", + "station", ] diff --git a/deebot_client/events/base_station.py b/deebot_client/events/station.py similarity index 75% rename from deebot_client/events/base_station.py rename to deebot_client/events/station.py index 39e609e1..4f4989cc 100644 --- a/deebot_client/events/base_station.py +++ b/deebot_client/events/station.py @@ -7,11 +7,11 @@ from .base import Event as _Event -__all__ = ["BaseStationEvent", "Status"] +__all__ = ["State", "StationEvent"] @unique -class Status(IntEnum): +class State(IntEnum): """Enum class for all possible base station statuses.""" IDLE = 0 @@ -19,7 +19,7 @@ class Status(IntEnum): @dataclass(frozen=True) -class BaseStationEvent(_Event): +class StationEvent(_Event): """Base Station Event representation.""" - state: Status + state: State diff --git a/deebot_client/hardware/deebot/buom7k.py b/deebot_client/hardware/deebot/buom7k.py index 4ad44625..614850fe 100644 --- a/deebot_client/hardware/deebot/buom7k.py +++ b/deebot_client/hardware/deebot/buom7k.py @@ -10,6 +10,7 @@ CapabilityCustomCommand, CapabilityEvent, CapabilityExecute, + CapabilityExecuteTypes, CapabilityLifeSpan, CapabilityMap, CapabilitySet, @@ -19,6 +20,8 @@ CapabilityStats, DeviceType, ) +from deebot_client.commands import StationAction +from deebot_client.commands.json import station_action from deebot_client.commands.json.auto_empty import GetAutoEmpty, SetAutoEmpty from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.carpet import ( @@ -48,7 +51,6 @@ from deebot_client.commands.json.play_sound import PlaySound from deebot_client.commands.json.pos import GetPos from deebot_client.commands.json.relocation import SetRelocationState -from deebot_client.commands.json.station_action import StationAction from deebot_client.commands.json.station_state import GetStationState from deebot_client.commands.json.stats import GetStats, GetTotalStats from deebot_client.commands.json.volume import GetVolume, SetVolume @@ -56,7 +58,6 @@ from deebot_client.const import DataType from deebot_client.events import ( AvailabilityEvent, - BaseStationEvent, BatteryEvent, CachedMapInfoEvent, CarpetAutoFanBoostEvent, @@ -79,6 +80,7 @@ ReportStatsEvent, RoomsEvent, StateEvent, + StationEvent, StatsEvent, TotalStatsEvent, VolumeEvent, @@ -100,7 +102,9 @@ AvailabilityEvent, [GetBattery(is_available_check=True)] ), base_station=CapabilityBaseStation( - action=StationAction, + action=CapabilityExecuteTypes( + station_action.StationAction, types=(StationAction.EMPTY_DUSTBIN,) + ), auto_empty=CapabilitySetTypes( event=AutoEmptyEvent, get=[GetAutoEmpty()], @@ -110,7 +114,7 @@ auto_empty.Frequency.SMART, ), ), - status=CapabilityEvent(BaseStationEvent, [GetStationState()]), + state=CapabilityEvent(StationEvent, [GetStationState()]), ), battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), diff --git a/deebot_client/hardware/deebot/p95mgv.py b/deebot_client/hardware/deebot/p95mgv.py index d587dcfe..660e44bb 100644 --- a/deebot_client/hardware/deebot/p95mgv.py +++ b/deebot_client/hardware/deebot/p95mgv.py @@ -10,6 +10,7 @@ CapabilityCustomCommand, CapabilityEvent, CapabilityExecute, + CapabilityExecuteTypes, CapabilityLifeSpan, CapabilityMap, CapabilitySet, @@ -19,6 +20,8 @@ CapabilityStats, DeviceType, ) +from deebot_client.commands import StationAction +from deebot_client.commands.json import station_action from deebot_client.commands.json.advanced_mode import GetAdvancedMode, SetAdvancedMode from deebot_client.commands.json.auto_empty import GetAutoEmpty, SetAutoEmpty from deebot_client.commands.json.battery import GetBattery @@ -57,7 +60,6 @@ from deebot_client.commands.json.play_sound import PlaySound from deebot_client.commands.json.pos import GetPos from deebot_client.commands.json.relocation import SetRelocationState -from deebot_client.commands.json.station_action import StationAction from deebot_client.commands.json.station_state import GetStationState from deebot_client.commands.json.stats import GetStats, GetTotalStats from deebot_client.commands.json.true_detect import GetTrueDetect, SetTrueDetect @@ -71,7 +73,6 @@ from deebot_client.events import ( AdvancedModeEvent, AvailabilityEvent, - BaseStationEvent, BatteryEvent, CachedMapInfoEvent, CarpetAutoFanBoostEvent, @@ -95,6 +96,7 @@ ReportStatsEvent, RoomsEvent, StateEvent, + StationEvent, StatsEvent, TotalStatsEvent, TrueDetectEvent, @@ -118,7 +120,9 @@ AvailabilityEvent, [GetBattery(is_available_check=True)] ), base_station=CapabilityBaseStation( - action=StationAction, + action=CapabilityExecuteTypes( + station_action.StationAction, types=(StationAction.EMPTY_DUSTBIN,) + ), auto_empty=CapabilitySetTypes( event=auto_empty.AutoEmptyEvent, get=[GetAutoEmpty()], @@ -130,7 +134,7 @@ auto_empty.Frequency.AUTO, ), ), - status=CapabilityEvent(BaseStationEvent, [GetStationState()]), + state=CapabilityEvent(StationEvent, [GetStationState()]), ), battery=CapabilityEvent(BatteryEvent, [GetBattery()]), charge=CapabilityExecute(Charge), diff --git a/deebot_client/hardware/deebot/qhe2o2.py b/deebot_client/hardware/deebot/qhe2o2.py index a2ed8674..9ffda83d 100644 --- a/deebot_client/hardware/deebot/qhe2o2.py +++ b/deebot_client/hardware/deebot/qhe2o2.py @@ -10,6 +10,7 @@ CapabilityCustomCommand, CapabilityEvent, CapabilityExecute, + CapabilityExecuteTypes, CapabilityLifeSpan, CapabilityMap, CapabilitySet, @@ -19,6 +20,8 @@ CapabilityStats, DeviceType, ) +from deebot_client.commands import StationAction +from deebot_client.commands.json import station_action from deebot_client.commands.json.auto_empty import GetAutoEmpty, SetAutoEmpty from deebot_client.commands.json.battery import GetBattery from deebot_client.commands.json.carpet import ( @@ -48,7 +51,6 @@ from deebot_client.commands.json.play_sound import PlaySound from deebot_client.commands.json.pos import GetPos from deebot_client.commands.json.relocation import SetRelocationState -from deebot_client.commands.json.station_action import StationAction from deebot_client.commands.json.station_state import GetStationState from deebot_client.commands.json.stats import GetStats, GetTotalStats from deebot_client.commands.json.volume import GetVolume, SetVolume @@ -57,7 +59,6 @@ from deebot_client.events import ( AutoEmptyEvent, AvailabilityEvent, - BaseStationEvent, BatteryEvent, CachedMapInfoEvent, CarpetAutoFanBoostEvent, @@ -80,6 +81,7 @@ ReportStatsEvent, RoomsEvent, StateEvent, + StationEvent, StatsEvent, TotalStatsEvent, VolumeEvent, @@ -101,7 +103,9 @@ ), battery=CapabilityEvent(BatteryEvent, [GetBattery()]), base_station=CapabilityBaseStation( - action=StationAction, + action=CapabilityExecuteTypes( + station_action.StationAction, types=(StationAction.EMPTY_DUSTBIN,) + ), auto_empty=CapabilitySetTypes( event=AutoEmptyEvent, get=[GetAutoEmpty()], @@ -111,7 +115,7 @@ auto_empty.Frequency.SMART, ), ), - status=CapabilityEvent(BaseStationEvent, [GetStationState()]), + state=CapabilityEvent(StationEvent, [GetStationState()]), ), charge=CapabilityExecute(Charge), clean=CapabilityClean( diff --git a/deebot_client/messages/json/station_state.py b/deebot_client/messages/json/station_state.py index 36ca1409..6d41aaf4 100644 --- a/deebot_client/messages/json/station_state.py +++ b/deebot_client/messages/json/station_state.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING, Any -from deebot_client.events.base_station import BaseStationEvent, Status +from deebot_client.events.station import State, StationEvent from deebot_client.message import HandlingResult, MessageBodyDataDict if TYPE_CHECKING: @@ -28,16 +28,16 @@ def _handle_body_data_dict( # "body":{"data":{"content":{"error":[],"type":1,"motionState":1},"state":1},"code":0,"msg":"ok"} - Emptying if (state := data.get("state")) == 0: - reported_state = Status.IDLE + reported_state = State.IDLE elif ( state == 1 and (content := data.get("content")) and content.get("type") == 1 and content.get("motionState") == 1 ): - reported_state = Status.EMPTYING + reported_state = State.EMPTYING else: return HandlingResult.analyse() - event_bus.notify(BaseStationEvent(reported_state)) + event_bus.notify(StationEvent(reported_state)) return HandlingResult.success() diff --git a/tests/commands/json/test_station_action.py b/tests/commands/json/test_station_action.py index 61470640..6625253e 100644 --- a/tests/commands/json/test_station_action.py +++ b/tests/commands/json/test_station_action.py @@ -6,8 +6,8 @@ import pytest -from deebot_client.commands import BaseStationAction -from deebot_client.commands.json.station_action import StationAction +from deebot_client.commands import StationAction +from deebot_client.commands.json import station_action from . import assert_execute_command @@ -16,15 +16,15 @@ ("action", "args"), [ ( - BaseStationAction.EMPTY_DUSTBIN, + StationAction.EMPTY_DUSTBIN, {"act": 1, "type": 1}, ), ], ) async def test_StationAction( - action: BaseStationAction, + action: StationAction, args: dict[str, Any], ) -> None: """Test StationAction.""" - command = StationAction(action) + command = station_action.StationAction(action) await assert_execute_command(command, args) diff --git a/tests/commands/json/test_station_state.py b/tests/commands/json/test_station_state.py index aa710468..512a697e 100644 --- a/tests/commands/json/test_station_state.py +++ b/tests/commands/json/test_station_state.py @@ -5,7 +5,7 @@ import pytest from deebot_client.commands.json.station_state import GetStationState -from deebot_client.events.base_station import BaseStationEvent, Status +from deebot_client.events.station import State, StationEvent from tests.helpers import get_request_json, get_success_body from . import assert_command @@ -14,14 +14,14 @@ @pytest.mark.parametrize( ("state", "additional_content", "expected"), [ - (0, {"type": 0}, Status.IDLE), - (1, {"type": 1, "motionState": 1}, Status.EMPTYING), + (0, {"type": 0}, State.IDLE), + (1, {"type": 1, "motionState": 1}, State.EMPTYING), ], ) async def test_GetStationState( state: int, additional_content: dict[str, Any], - expected: Status, + expected: State, ) -> None: json = get_request_json( get_success_body( @@ -31,4 +31,4 @@ async def test_GetStationState( } ) ) - await assert_command(GetStationState(), json, BaseStationEvent(expected)) + await assert_command(GetStationState(), json, StationEvent(expected)) diff --git a/tests/hardware/test_init.py b/tests/hardware/test_init.py index 23fa42c4..6a7b2db4 100644 --- a/tests/hardware/test_init.py +++ b/tests/hardware/test_init.py @@ -45,7 +45,6 @@ AdvancedModeEvent, AutoEmptyEvent, AvailabilityEvent, - BaseStationEvent, BatteryEvent, BorderSwitchEvent, CarpetAutoFanBoostEvent, @@ -67,6 +66,7 @@ RoomsEvent, SafeProtectEvent, StateEvent, + StationEvent, StatsEvent, TotalStatsEvent, TrueDetectEvent, @@ -198,7 +198,7 @@ async def test_get_static_device_info( AutoEmptyEvent: [GetAutoEmpty()], AdvancedModeEvent: [GetAdvancedMode()], AvailabilityEvent: [GetBattery(is_available_check=True)], - BaseStationEvent: [GetStationState()], + StationEvent: [GetStationState()], BatteryEvent: [GetBattery()], CachedMapInfoEvent: [GetCachedMapInfo()], CarpetAutoFanBoostEvent: [GetCarpetAutoFanBoost()], diff --git a/tests/messages/json/test_station_state.py b/tests/messages/json/test_station_state.py index e862aa07..e1bf4084 100644 --- a/tests/messages/json/test_station_state.py +++ b/tests/messages/json/test_station_state.py @@ -4,7 +4,7 @@ import pytest -from deebot_client.events.base_station import BaseStationEvent, Status +from deebot_client.events.station import State, StationEvent from deebot_client.messages.json.station_state import OnStationState from tests.messages import assert_message @@ -12,14 +12,14 @@ @pytest.mark.parametrize( ("state", "additional_content", "expected"), [ - (0, {"type": 0}, Status.IDLE), - (1, {"type": 1, "motionState": 1}, Status.EMPTYING), + (0, {"type": 0}, State.IDLE), + (1, {"type": 1, "motionState": 1}, State.EMPTYING), ], ) def test_onStationState( state: int, additional_content: dict[str, Any], - expected: Status, + expected: State, ) -> None: data: dict[str, Any] = { "header": { @@ -38,4 +38,4 @@ def test_onStationState( }, } - assert_message(OnStationState, data, BaseStationEvent(expected)) + assert_message(OnStationState, data, StationEvent(expected))