Skip to content

Commit ab2de5b

Browse files
Lash-Lallenporter
andauthored
feat: add basic schedule getting (#675)
* feat: add basic schedule getting * chore: apply suggestions from code review Co-authored-by: Allen Porter <allen.porter@gmail.com> * chore: exception --------- Co-authored-by: Allen Porter <allen.porter@gmail.com>
1 parent 85b7bee commit ab2de5b

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

roborock/data/containers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,15 @@ class HomeDataScene(RoborockBase):
284284
name: str
285285

286286

287+
@dataclass
288+
class HomeDataSchedule(RoborockBase):
289+
id: int
290+
cron: str
291+
repeated: bool
292+
enabled: bool
293+
param: dict | None = None
294+
295+
287296
@dataclass
288297
class HomeData(RoborockBase):
289298
id: int

roborock/web_api.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from aiohttp import ContentTypeError, FormData
1515
from pyrate_limiter import BucketFullException, Duration, Limiter, Rate
1616

17+
from roborock import HomeDataSchedule
1718
from roborock.data import HomeData, HomeDataRoom, HomeDataScene, ProductResponse, RRiot, UserData
1819
from roborock.exceptions import (
1920
RoborockAccountDoesNotExist,
@@ -607,6 +608,28 @@ async def execute_scene(self, user_data: UserData, scene_id: int) -> None:
607608
if not execute_scene_response.get("success"):
608609
raise RoborockException(execute_scene_response)
609610

611+
async def get_schedules(self, user_data: UserData, device_id: str) -> list[HomeDataSchedule]:
612+
rriot = user_data.rriot
613+
if rriot is None:
614+
raise RoborockException("rriot is none")
615+
if rriot.r.a is None:
616+
raise RoborockException("Missing field 'a' in rriot reference")
617+
schedules_request = PreparedRequest(
618+
rriot.r.a,
619+
self.session,
620+
{
621+
"Authorization": _get_hawk_authentication(rriot, f"/user/devices/{device_id}/jobs"),
622+
},
623+
)
624+
schedules_response = await schedules_request.request("get", f"/user/devices/{str(device_id)}/jobs")
625+
if not schedules_response.get("success"):
626+
raise RoborockException(schedules_response)
627+
schedules = schedules_response.get("result")
628+
if isinstance(schedules, list):
629+
return [HomeDataSchedule.from_dict(schedule) for schedule in schedules]
630+
else:
631+
raise RoborockException(f"schedule_response result was an unexpected type: {schedules}")
632+
610633
async def get_products(self, user_data: UserData) -> ProductResponse:
611634
"""Gets all products and their schemas, good for determining status codes and model numbers."""
612635
base_url = await self.base_url

tests/test_web_api.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,52 @@ async def test_missing_country_login(mock_rest) -> None:
203203
assert ud is not None
204204
# Ensure we have no surprise REST calls.
205205
assert len(mock_rest.requests) == 3
206+
207+
208+
async def test_get_schedules(mock_rest) -> None:
209+
"""Test that we can get schedules."""
210+
api = RoborockApiClient(username="test_user@gmail.com")
211+
ud = await api.pass_login("password")
212+
213+
# Mock the response
214+
mock_rest.get(
215+
"https://api-us.roborock.com/user/devices/123456/jobs",
216+
status=200,
217+
payload={
218+
"api": None,
219+
"result": [
220+
{
221+
"id": 3878757,
222+
"cron": "03 13 15 12 ?",
223+
"repeated": False,
224+
"enabled": True,
225+
"param": {
226+
"id": 1,
227+
"method": "server_scheduled_start",
228+
"params": [
229+
{
230+
"repeat": 1,
231+
"water_box_mode": 202,
232+
"segments": "0",
233+
"fan_power": 102,
234+
"mop_mode": 300,
235+
"clean_mop": 1,
236+
"map_index": -1,
237+
"name": "1765735413736",
238+
}
239+
],
240+
},
241+
}
242+
],
243+
"status": "ok",
244+
"success": True,
245+
},
246+
)
247+
248+
schedules = await api.get_schedules(ud, "123456")
249+
assert len(schedules) == 1
250+
schedule = schedules[0]
251+
assert schedule.id == 3878757
252+
assert schedule.cron == "03 13 15 12 ?"
253+
assert schedule.repeated is False
254+
assert schedule.enabled is True

0 commit comments

Comments
 (0)