Skip to content

Commit

Permalink
Rename vacuum_bot to device (#334)
Browse files Browse the repository at this point in the history
  • Loading branch information
edenhaus authored Oct 27, 2023
1 parent af82898 commit 8e1b7aa
Show file tree
Hide file tree
Showing 18 changed files with 68 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ body:
validations:
required: true
attributes:
label: On which deebot vacuum you have the issue?
label: On which deebot device (vacuum) you have the issue?
placeholder: Deebot Ozmo 950
- type: input
id: version
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Client Library for Deebot Vacuums
# Client Library for Deebot devices (Vacuums)

[![PyPI - Downloads](https://img.shields.io/pypi/dw/deebot-client?style=for-the-badge)](https://pypi.org/project/deebot-client)
<a href="https://www.buymeacoffee.com/edenhaus" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-black.png" width="150px" height="35px" alt="Buy Me A Coffee" style="height: 35px !important;width: 150px !important;" ></a>
Expand Down Expand Up @@ -31,7 +31,7 @@ from deebot_client.events import BatteryEvent
from deebot_client.models import Configuration
from deebot_client.mqtt_client import MqttClient, MqttConfiguration
from deebot_client.util import md5
from deebot_client.vacuum_bot import VacuumBot
from deebot_client.device import Device

device_id = md5(str(time.time()))
account_id = "your email or phonenumber (cn)"
Expand All @@ -52,7 +52,7 @@ async def main():

devices_ = await api_client.get_devices()

bot = VacuumBot(devices_[0], authenticator)
bot = Device(devices_[0], authenticator)

mqtt_config = MqttConfiguration(config=config)
mqtt = MqttClient(mqtt_config, authenticator)
Expand Down
6 changes: 3 additions & 3 deletions deebot_client/commands/json/charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from deebot_client.events import StateEvent
from deebot_client.logging_filter import get_logger
from deebot_client.message import HandlingResult
from deebot_client.models import VacuumState
from deebot_client.models import State

from .common import ExecuteCommand
from .const import CODE
Expand All @@ -29,12 +29,12 @@ def _handle_body(cls, event_bus: EventBus, body: dict[str, Any]) -> HandlingResu
"""
code = int(body.get(CODE, -1))
if code == 0:
event_bus.notify(StateEvent(VacuumState.RETURNING))
event_bus.notify(StateEvent(State.RETURNING))
return HandlingResult.success()

if code == 30007:
# bot is already charging
event_bus.notify(StateEvent(VacuumState.DOCKED))
event_bus.notify(StateEvent(State.DOCKED))
return HandlingResult.success()

return super()._handle_body(event_bus, body)
12 changes: 6 additions & 6 deletions deebot_client/commands/json/charge_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from deebot_client.event_bus import EventBus
from deebot_client.events import StateEvent
from deebot_client.message import HandlingResult, MessageBodyDataDict
from deebot_client.models import VacuumState
from deebot_client.models import State

from .common import CommandWithMessageHandling
from .const import CODE
Expand All @@ -24,7 +24,7 @@ def _handle_body_data_dict(
:return: A message response
"""
if data.get("isCharging") == 1:
event_bus.notify(StateEvent(VacuumState.DOCKED))
event_bus.notify(StateEvent(State.DOCKED))
return HandlingResult.success()

@classmethod
Expand All @@ -33,17 +33,17 @@ def _handle_body(cls, event_bus: EventBus, body: dict[str, Any]) -> HandlingResu
# Call this also if code is not in the body
return super()._handle_body(event_bus, body)

status: VacuumState | None = None
status: State | None = None
if body.get("msg", None) == "fail":
if body["code"] == "30007": # Already charging
status = VacuumState.DOCKED
status = State.DOCKED
elif body["code"] in ("3", "5"):
# 3 -> Bot in stuck state, example dust bin out
# 5 -> Busy with another command
status = VacuumState.ERROR
status = State.ERROR

if status:
event_bus.notify(StateEvent(VacuumState.DOCKED))
event_bus.notify(StateEvent(State.DOCKED))
return HandlingResult.success()

return HandlingResult.analyse()
20 changes: 10 additions & 10 deletions deebot_client/commands/json/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from deebot_client.events import StateEvent
from deebot_client.logging_filter import get_logger
from deebot_client.message import HandlingResult, MessageBodyDataDict
from deebot_client.models import CleanAction, CleanMode, DeviceInfo, VacuumState
from deebot_client.models import CleanAction, CleanMode, DeviceInfo, State

from .common import CommandWithMessageHandling, ExecuteCommand

Expand All @@ -30,12 +30,12 @@ async def _execute(
if state and isinstance(self._args, dict):
if (
self._args["act"] == CleanAction.RESUME.value
and state.state != VacuumState.PAUSED
and state.state != State.PAUSED
):
self._args = self.__get_args(CleanAction.START)
elif (
self._args["act"] == CleanAction.START.value
and state.state == VacuumState.PAUSED
and state.state == State.PAUSED
):
self._args = self.__get_args(CleanAction.RESUME)

Expand Down Expand Up @@ -76,19 +76,19 @@ def _handle_body_data_dict(
:return: A message response
"""

status: VacuumState | None = None
status: State | None = None
state = data.get("state")
if data.get("trigger") == "alert":
status = VacuumState.ERROR
status = State.ERROR
elif state == "clean":
clean_state = data.get("cleanState", {})
motion_state = clean_state.get("motionState")
if motion_state == "working":
status = VacuumState.CLEANING
status = State.CLEANING
elif motion_state == "pause":
status = VacuumState.PAUSED
status = State.PAUSED
elif motion_state == "goCharging":
status = VacuumState.RETURNING
status = State.RETURNING

clean_type = clean_state.get("type")
content = clean_state.get("content", {})
Expand All @@ -103,9 +103,9 @@ def _handle_body_data_dict(
_LOGGER.debug("Last custom area values (x1,y1,x2,y2): %s", area_values)

elif state == "goCharging":
status = VacuumState.RETURNING
status = State.RETURNING
elif state == "idle":
status = VacuumState.IDLE
status = State.IDLE

if status:
event_bus.notify(StateEvent(status))
Expand Down
4 changes: 2 additions & 2 deletions deebot_client/commands/json/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def _handle_response(
case 4200:
# bot offline
_LOGGER.info(
'Vacuum is offline. Could not execute command "%s"', self.name
'Device is offline. Could not execute command "%s"', self.name
)
event_bus.notify(AvailabilityEvent(False))
return CommandResult(HandlingState.FAILED)
Expand All @@ -75,7 +75,7 @@ def _handle_response(
)
else:
_LOGGER.warning(
'No response received for command "%s". This can happen if the vacuum has network issues or does not support the command',
'No response received for command "%s". This can happen if the device has network issues or does not support the command',
self.name,
)
return CommandResult(HandlingState.FAILED)
Expand Down
4 changes: 2 additions & 2 deletions deebot_client/commands/json/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from deebot_client.event_bus import EventBus
from deebot_client.events import ErrorEvent, StateEvent
from deebot_client.message import HandlingResult, MessageBodyDataDict
from deebot_client.models import VacuumState
from deebot_client.models import State

from .common import CommandWithMessageHandling

Expand All @@ -30,7 +30,7 @@ def _handle_body_data_dict(
if error is not None:
description = _ERROR_CODES.get(error)
if error != 0:
event_bus.notify(StateEvent(VacuumState.ERROR))
event_bus.notify(StateEvent(State.ERROR))
event_bus.notify(ErrorEvent(error, description))
return HandlingResult.success()

Expand Down
12 changes: 6 additions & 6 deletions deebot_client/vacuum_bot.py → deebot_client/device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Vacuum bot module."""
"""Device module."""
import asyncio
from collections.abc import Callable
from contextlib import suppress
Expand Down Expand Up @@ -27,14 +27,14 @@
from .logging_filter import get_logger
from .map import Map
from .messages import get_message
from .models import DeviceInfo, VacuumState
from .models import DeviceInfo, State

_LOGGER = get_logger(__name__)
_AVAILABLE_CHECK_INTERVAL = 60


class VacuumBot:
"""Vacuum bot representation."""
class Device:
"""Device representation."""

def __init__(
self,
Expand All @@ -60,7 +60,7 @@ def __init__(
self.map: Final[Map] = Map(self.execute_command, self.events)

async def on_pos(event: PositionsEvent) -> None:
if self._state == StateEvent(VacuumState.DOCKED):
if self._state == StateEvent(State.DOCKED):
return

deebot = next(p for p in event.positions if p.type == PositionType.DEEBOT)
Expand All @@ -79,7 +79,7 @@ async def on_pos(event: PositionsEvent) -> None:
self.events.subscribe(PositionsEvent, on_pos)

async def on_state(event: StateEvent) -> None:
if event.state == VacuumState.DOCKED:
if event.state == State.DOCKED:
self.events.request_refresh(CleanLogEvent)
self.events.request_refresh(TotalStatsEvent)

Expand Down
8 changes: 4 additions & 4 deletions deebot_client/event_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .events import AvailabilityEvent, Event, StateEvent
from .logging_filter import get_logger
from .models import VacuumState
from .models import State
from .util import cancel, create_task

if TYPE_CHECKING:
Expand Down Expand Up @@ -93,13 +93,13 @@ def _notify(event: T) -> None:

if (
isinstance(event, StateEvent)
and event.state == VacuumState.IDLE
and event.state == State.IDLE
and event_processing_data.last_event
and event_processing_data.last_event.state == VacuumState.DOCKED # type: ignore[attr-defined]
and event_processing_data.last_event.state == State.DOCKED # type: ignore[attr-defined]
):
# todo distinguish better between docked and idle and outside event bus. # pylint: disable=fixme
# Problem getCleanInfo will return state=idle, when bot is charging
event = StateEvent(VacuumState.DOCKED) # type: ignore[assignment]
event = StateEvent(State.DOCKED) # type: ignore[assignment]
elif (
isinstance(event, AvailabilityEvent)
and event.available
Expand Down
4 changes: 2 additions & 2 deletions deebot_client/events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Any

from deebot_client.events.base import Event
from deebot_client.models import Room, VacuumState
from deebot_client.models import Room, State
from deebot_client.util import DisplayNameIntEnum

from .fan_speed import FanSpeedEvent, FanSpeedLevel
Expand Down Expand Up @@ -175,7 +175,7 @@ class AvailabilityEvent(Event):
class StateEvent(Event):
"""State event representation."""

state: VacuumState
state: State


@dataclass(frozen=True)
Expand Down
4 changes: 2 additions & 2 deletions deebot_client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ class Room:


@unique
class VacuumState(IntEnum):
"""Vacuum state representation."""
class State(IntEnum):
"""State representation."""

IDLE = 1
CLEANING = 2
Expand Down
2 changes: 1 addition & 1 deletion deebot_client/mqtt_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def last_message_received_at(self) -> datetime | None:
return self._last_message_received_at

async def subscribe(self, info: SubscriberInfo) -> Callable[[], None]:
"""Subscribe for messages from given vacuum."""
"""Subscribe for messages from given device."""
await self.connect()
self._subscribtion_changes.put_nowait((info, True))

Expand Down
6 changes: 3 additions & 3 deletions tests/commands/json/test_charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from deebot_client.commands.json import Charge
from deebot_client.events import StateEvent
from deebot_client.models import VacuumState
from deebot_client.models import State
from tests.helpers import get_request_json, get_success_body

from . import assert_command
Expand All @@ -25,8 +25,8 @@ def _prepare_json(code: int, msg: str = "ok") -> dict[str, Any]:
@pytest.mark.parametrize(
("json", "expected"),
[
(get_request_json(get_success_body()), StateEvent(VacuumState.RETURNING)),
(_prepare_json(30007), StateEvent(VacuumState.DOCKED)),
(get_request_json(get_success_body()), StateEvent(State.RETURNING)),
(_prepare_json(30007), StateEvent(State.DOCKED)),
],
)
async def test_Charge(json: dict[str, Any], expected: StateEvent) -> None:
Expand Down
18 changes: 9 additions & 9 deletions tests/commands/json/test_clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from deebot_client.commands.json.clean import Clean, CleanAction
from deebot_client.event_bus import EventBus
from deebot_client.events import StateEvent
from deebot_client.models import DeviceInfo, VacuumState
from deebot_client.models import DeviceInfo, State
from tests.helpers import get_request_json, get_success_body

from . import assert_command
Expand All @@ -19,7 +19,7 @@
[
(
get_request_json(get_success_body({"trigger": "none", "state": "idle"})),
StateEvent(VacuumState.IDLE),
StateEvent(State.IDLE),
),
],
)
Expand All @@ -28,26 +28,26 @@ async def test_GetCleanInfo(json: dict[str, Any], expected: StateEvent) -> None:


@pytest.mark.parametrize(
("action", "vacuum_state", "expected"),
("action", "state", "expected"),
[
(CleanAction.START, None, CleanAction.START),
(CleanAction.START, VacuumState.PAUSED, CleanAction.RESUME),
(CleanAction.START, VacuumState.DOCKED, CleanAction.START),
(CleanAction.START, State.PAUSED, CleanAction.RESUME),
(CleanAction.START, State.DOCKED, CleanAction.START),
(CleanAction.RESUME, None, CleanAction.RESUME),
(CleanAction.RESUME, VacuumState.PAUSED, CleanAction.RESUME),
(CleanAction.RESUME, VacuumState.DOCKED, CleanAction.START),
(CleanAction.RESUME, State.PAUSED, CleanAction.RESUME),
(CleanAction.RESUME, State.DOCKED, CleanAction.START),
],
)
async def test_Clean_act(
authenticator: Authenticator,
device_info: DeviceInfo,
action: CleanAction,
vacuum_state: VacuumState | None,
state: State | None,
expected: CleanAction,
) -> None:
event_bus = Mock(spec_set=EventBus)
event_bus.get_last_event.return_value = (
StateEvent(vacuum_state) if vacuum_state is not None else None
StateEvent(state) if state is not None else None
)
command = Clean(action)

Expand Down
4 changes: 2 additions & 2 deletions tests/commands/json/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _assert_false_and_avalable_event_false(available: bool, event_bus: Mock) ->
_ERROR_500,
(
logging.WARNING,
'No response received for command "{}". This can happen if the vacuum has network issues or does not support the command',
'No response received for command "{}". This can happen if the device has network issues or does not support the command',
),
_assert_false_and_not_called,
),
Expand All @@ -54,7 +54,7 @@ def _assert_false_and_avalable_event_false(available: bool, event_bus: Mock) ->
_ERROR_4200,
(
logging.INFO,
'Vacuum is offline. Could not execute command "{}"',
'Device is offline. Could not execute command "{}"',
),
_assert_false_and_avalable_event_false,
),
Expand Down
Loading

0 comments on commit 8e1b7aa

Please sign in to comment.