Skip to content

Commit

Permalink
Bring new changes (#1)
Browse files Browse the repository at this point in the history
* fix: handle weird clean record response (humbertogontijo#206)

* 2.2.2

Automatically generated by python-semantic-release

* chore: Update documentation for reset_consumable (humbertogontijo#207)

Document parameter for API function reset_consumable

* chore: add load multi map parameter to docs(humbertogontijo#209)

* S8 maxv highest mop intensity setting (humbertogontijo#210)

* fix: s8 maxv has a wash and fill dock (humbertogontijo#213)

* 2.2.3

Automatically generated by python-semantic-release

* S8MaxVUltra is missing some code mappings (humbertogontijo#214)

* fix: add missing smart mode for s8 maxv dock

* fix: add missing modes for s8 maxv ultra

* fix: add missing modes for s8 maxv ultra

* feat: add warning in web requests if it fails to decode (humbertogontijo#215)

* 2.3.0

Automatically generated by python-semantic-release

* feat: add some missing codes and make warnings only message once (humbertogontijo#218)

* 2.4.0

Automatically generated by python-semantic-release

* feat: add some typing (humbertogontijo#219)

* 2.5.0

Automatically generated by python-semantic-release

---------

Co-authored-by: Luke Lashley <[email protected]>
Co-authored-by: github-actions <[email protected]>
Co-authored-by: Benjamin Paul [MSFT] <[email protected]>
Co-authored-by: PatrikTheDev <[email protected]>
Co-authored-by: Ethem Cem Özkan <[email protected]>
Co-authored-by: Willy <[email protected]>
  • Loading branch information
7 people authored Jun 28, 2024
1 parent 31697f6 commit 7f5cea5
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 23 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,36 @@

<!--next-version-placeholder-->

## v2.5.0 (2024-06-25)

### Feature

* Add some typing ([#219](https://github.com/humbertogontijo/python-roborock/issues/219)) ([`35d0900`](https://github.com/humbertogontijo/python-roborock/commit/35d09000b8d144cbaf935069952ea135950d0e78))

## v2.4.0 (2024-06-25)

### Feature

* Add some missing codes and make warnings only message once ([#218](https://github.com/humbertogontijo/python-roborock/issues/218)) ([`12361b5`](https://github.com/humbertogontijo/python-roborock/commit/12361b58e7a4d368281c4ffd9ac3d8e9d8155e62))

## v2.3.0 (2024-06-07)

### Feature

* Add warning in web requests if it fails to decode ([#215](https://github.com/humbertogontijo/python-roborock/issues/215)) ([`6ae69e9`](https://github.com/humbertogontijo/python-roborock/commit/6ae69e9bcba6a98736f2f480114922186f6ca458))

## v2.2.3 (2024-06-04)

### Fix

* S8 maxv has a wash and fill dock ([#213](https://github.com/humbertogontijo/python-roborock/issues/213)) ([`018fd05`](https://github.com/humbertogontijo/python-roborock/commit/018fd052360dffd238919e336943809720457c4e))

## v2.2.2 (2024-05-16)

### Fix

* Handle weird clean record response ([#206](https://github.com/humbertogontijo/python-roborock/issues/206)) ([`07ce71a`](https://github.com/humbertogontijo/python-roborock/commit/07ce71a2cd8085136952bd7639f6f4a2e273faf9))

## v2.2.1 (2024-05-11)

### Fix
Expand Down
6 changes: 4 additions & 2 deletions docs/source/api_commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,9 @@ reset_consumable

Description:

Parameters:
Parameters: List of consumables to reset. For example, to reset consumables 'strainer_work_times' and 'sensor_dirty_time' the parameter would be

['strainer_work_times', 'sensor_dirty_time']

====================== =========
Vacuum Model Supported
Expand Down Expand Up @@ -1247,7 +1249,7 @@ load_multi_map

Description:

Parameters: ???
Parameters: number (the floor/map index)

..
Need to work out parameter format
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "python-roborock"
version = "2.2.1"
version = "2.5.0"
description = "A package to control Roborock vacuums."
authors = ["humbertogontijo <[email protected]>"]
license = "GPL-3.0-only"
Expand Down
104 changes: 102 additions & 2 deletions roborock/code_mappings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from enum import Enum, IntEnum

_LOGGER = logging.getLogger(__name__)
completed_warnings = set()


class RoborockEnum(IntEnum):
Expand All @@ -16,10 +17,16 @@ def name(self) -> str:
@classmethod
def _missing_(cls: type[RoborockEnum], key) -> RoborockEnum:
if hasattr(cls, "unknown"):
_LOGGER.warning(f"Missing {cls.__name__} code: {key} - defaulting to 'unknown'")
warning = f"Missing {cls.__name__} code: {key} - defaulting to 'unknown'"
if warning not in completed_warnings:
completed_warnings.add(warning)
_LOGGER.warning(warning)
return cls.unknown # type: ignore
default_value = next(item for item in cls)
_LOGGER.warning(f"Missing {cls.__name__} code: {key} - defaulting to {default_value}")
warning = f"Missing {cls.__name__} code: {key} - defaulting to {default_value}"
if warning not in completed_warnings:
completed_warnings.add(warning)
_LOGGER.warning(warning)
return default_value

@classmethod
Expand Down Expand Up @@ -248,7 +255,10 @@ class RoborockFanSpeedP10(RoborockFanPowerCode):

class RoborockFanSpeedS8MaxVUltra(RoborockFanPowerCode):
off = 105
quiet = 101
balanced = 102
turbo = 103
max = 104
custom = 106
max_plus = 108
smart_mode = 110
Expand Down Expand Up @@ -324,6 +334,8 @@ class RoborockMopIntensityS8MaxVUltra(RoborockMopIntensityCode):
low = 201
medium = 202
high = 203
custom = 204
max = 208
smart_mode = 209
custom_water_flow = 207

Expand Down Expand Up @@ -394,6 +406,7 @@ class RoborockDockWashTowelModeCode(RoborockEnum):
light = 0
balanced = 1
deep = 2
smart = 10


class RoborockCategory(Enum):
Expand All @@ -409,6 +422,93 @@ def __missing__(self, key):
return RoborockCategory.UNKNOWN


class RoborockFinishReason(RoborockEnum):
manual_interrupt = 21 # Cleaning interrupted by user
cleanup_interrupted = 24 # Cleanup interrupted
manual_interrupt_2 = 21
breakpoint = 32 # Could not continue cleaning
breakpoint_2 = 33
cleanup_interrupted_2 = 34
manual_interrupt_3 = 35
manual_interrupt_4 = 36
manual_interrupt_5 = 37
manual_interrupt_6 = 43
locate_fail = 45 # Positioning Failed
cleanup_interrupted_3 = 64
locate_fail_2 = 65
manual_interrupt_7 = 48
manual_interrupt_8 = 49
manual_interrupt_9 = 50
cleanup_interrupted_4 = 51
finished_cleaning = 52 # Finished cleaning
finished_cleaning_2 = 54
finished_cleaning_3 = 55
finished_cleaning_4 = 56
finished_clenaing_5 = 57
manual_interrupt_10 = 60
area_unreachable = 61 # Area unreachable
area_unreachable_2 = 62
washing_error = 67 # Washing error
back_to_wash_failure = 68 # Failed to return to the dock
cleanup_interrupted_5 = 101
breakpoint_4 = 102
manual_interrupt_11 = 103
cleanup_interrupted_6 = 104
cleanup_interrupted_7 = 105
cleanup_interrupted_8 = 106
cleanup_interrupted_9 = 107
cleanup_interrupted_10 = 109
cleanup_interrupted_11 = 110
patrol_success = 114 # Cruise completed
patrol_fail = 115 # Cruise failed
pet_patrol_success = 116 # Pet found
pet_patrol_fail = 117 # Pet found failed


class RoborockInCleaning(RoborockEnum):
complete = 0
global_clean_not_complete = 1
zone_clean_not_complete = 2
segment_clean_not_complete = 3


class RoborockCleanType(RoborockEnum):
all_zone = 1
draw_zone = 2
select_zone = 3
quick_build = 4
video_patrol = 5
pet_patrol = 6


class RoborockStartType(RoborockEnum):
button = 1
app = 2
schedule = 3
mi_home = 4
quick_start = 5
voice_control = 13
routines = 101
alexa = 801
google = 802
ifttt = 803
yandex = 804
homekit = 805
xiaoai = 806
tmall_genie = 807
duer = 808
dingdong = 809
siri = 810
clova = 811
wechat = 901
alipay = 902
aqara = 903
hisense = 904
huawei = 905
widget_launch = 820
smart_watch = 821


class DyadSelfCleanMode(RoborockEnum):
self_clean = 1
self_clean_and_dry = 2
Expand Down
5 changes: 4 additions & 1 deletion roborock/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@
ROBOROCK_C1 = "roborock.vacuum.c1"
ROBOROCK_S8_PRO_ULTRA = "roborock.vacuum.a70"
ROBOROCK_S8 = "roborock.vacuum.a51"
ROBOROCK_P10 = "roborock.vacuum.a75"
ROBOROCK_P10 = "roborock.vacuum.a75" # also known as q_revo
ROBOROCK_S8_MAXV_ULTRA = "roborock.vacuum.a97"
ROBOROCK_QREVO_S = "roborock.vacuum.a104"
ROBOROCK_QREVO_PRO = "roborock.vacuum.a101"
ROBOROCK_QREVO_MAXV = "roborock.vacuum.a87"

ROBOROCK_DYAD_AIR = "roborock.wetdryvac.a107"
ROBOROCK_DYAD_PRO_COMBO = "roborock.wetdryvac.a83"
Expand Down
21 changes: 17 additions & 4 deletions roborock/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .code_mappings import (
RoborockCategory,
RoborockCleanType,
RoborockDockDustCollectionModeCode,
RoborockDockErrorCode,
RoborockDockTypeCode,
Expand All @@ -25,6 +26,8 @@
RoborockFanSpeedS7,
RoborockFanSpeedS7MaxV,
RoborockFanSpeedS8MaxVUltra,
RoborockFinishReason,
RoborockInCleaning,
RoborockMopIntensityCode,
RoborockMopIntensityP10,
RoborockMopIntensityS5Max,
Expand All @@ -36,6 +39,7 @@
RoborockMopModeS7,
RoborockMopModeS8MaxVUltra,
RoborockMopModeS8ProUltra,
RoborockStartType,
RoborockStateCode,
)
from .const import (
Expand All @@ -47,6 +51,9 @@
ROBOROCK_G10S_PRO,
ROBOROCK_P10,
ROBOROCK_Q7_MAX,
ROBOROCK_QREVO_MAXV,
ROBOROCK_QREVO_PRO,
ROBOROCK_QREVO_S,
ROBOROCK_S4_MAX,
ROBOROCK_S5_MAX,
ROBOROCK_S6,
Expand Down Expand Up @@ -408,7 +415,7 @@ class Status(RoborockBase):
square_meter_clean_area: float | None = None
error_code: RoborockErrorCode | None = None
map_present: int | None = None
in_cleaning: int | None = None
in_cleaning: RoborockInCleaning | None = None
in_returning: int | None = None
in_fresh_state: int | None = None
lab_status: int | None = None
Expand Down Expand Up @@ -574,6 +581,12 @@ class S8MaxvUltraStatus(Status):
ROBOROCK_S8_PRO_ULTRA: S8ProUltraStatus,
ROBOROCK_G10S_PRO: S7MaxVStatus,
ROBOROCK_P10: P10Status,
# These likely are not correct,
# but i am currently unable to do my typical reverse engineering/ get any data from users on this,
# so this will be here in the mean time.
ROBOROCK_QREVO_S: P10Status,
ROBOROCK_QREVO_MAXV: P10Status,
ROBOROCK_QREVO_PRO: P10Status,
ROBOROCK_S8_MAXV_ULTRA: S8MaxvUltraStatus,
}

Expand Down Expand Up @@ -613,9 +626,9 @@ class CleanRecord(RoborockBase):
square_meter_area: float | None = None
error: int | None = None
complete: int | None = None
start_type: int | None = None
clean_type: int | None = None
finish_reason: int | None = None
start_type: RoborockStartType | None = None
clean_type: RoborockCleanType | None = None
finish_reason: RoborockFinishReason | None = None
dust_collection_status: int | None = None
avoid_count: int | None = None
wash_count: int | None = None
Expand Down
2 changes: 1 addition & 1 deletion roborock/local_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ async def hello(self):
except Exception as e:
self._logger.error(e)

async def ping(self):
async def ping(self) -> None:
request_id = 2
protocol = RoborockMessageProtocol.PING_REQUEST
return await self.send_message(
Expand Down
27 changes: 23 additions & 4 deletions roborock/version_1_apis/roborock_client_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
RoborockDockTypeCode.empty_wash_fill_dock,
RoborockDockTypeCode.s8_dock,
RoborockDockTypeCode.p10_dock,
RoborockDockTypeCode.s8_maxv_ultra_dock,
]
RT = TypeVar("RT", bound=RoborockBase)
EVICT_TIME = 60
Expand Down Expand Up @@ -104,7 +105,7 @@ async def async_value(self):
def stop(self):
self.task.cancel()

async def update_value(self, params):
async def update_value(self, params) -> None:
if self.attribute.set_command is None:
raise RoborockException(f"{self.attribute.attribute} have no set command")
response = await self.api._send_command(self.attribute.set_command, params)
Expand All @@ -118,7 +119,7 @@ async def add_value(self, params):
await self._async_value()
return response

async def close_value(self, params=None):
async def close_value(self, params=None) -> None:
if self.attribute.close_command is None:
raise RoborockException(f"{self.attribute.attribute} have no close command")
response = await self.api._send_command(self.attribute.close_command, params)
Expand Down Expand Up @@ -153,7 +154,7 @@ def release(self):
super().release()
[item.stop() for item in self.cache.values()]

async def async_release(self):
async def async_release(self) -> None:
await super().async_release()
[item.stop() for item in self.cache.values()]

Expand Down Expand Up @@ -197,6 +198,24 @@ async def get_clean_record(self, record_id: int) -> CleanRecord | None:
if isinstance(record, dict):
return CleanRecord.from_dict(record)
elif isinstance(record, list):
if isinstance(record[-1], dict):
records = [CleanRecord.from_dict(rec) for rec in record]
final_record = records[-1]
try:
# This code is semi-presumptions - so it is put in a try finally to be safe.
final_record.begin = records[0].begin
final_record.begin_datetime = records[0].begin_datetime
final_record.start_type = records[0].start_type
for rec in records[0:-1]:
final_record.duration += rec.duration if rec.duration is not None else 0
final_record.area += rec.area if rec.area is not None else 0
final_record.avoid_count += rec.avoid_count if rec.avoid_count is not None else 0
final_record.wash_count += rec.wash_count if rec.wash_count is not None else 0
final_record.square_meter_area += (
rec.square_meter_area if rec.square_meter_area is not None else 0
)
finally:
return final_record
# There are still a few unknown variables in this.
begin, end, duration, area = unpack_list(record, 4)
return CleanRecord(begin=begin, end=end, duration=duration, area=area)
Expand Down Expand Up @@ -277,7 +296,7 @@ async def get_room_mapping(self) -> list[RoomMapping] | None:
"""Gets the mapping from segment id -> iot id. Only works on local api."""
mapping: list = await self.send_command(RoborockCommand.GET_ROOM_MAPPING)
if isinstance(mapping, list):
if not isinstance(mapping[0], list) and len(mapping) == 2:
if len(mapping) == 2 and not isinstance(mapping[0], list):
return [RoomMapping(segment_id=mapping[0], iot_id=mapping[1])]
return [
RoomMapping(segment_id=segment_id, iot_id=iot_id) # type: ignore
Expand Down
Loading

0 comments on commit 7f5cea5

Please sign in to comment.