Skip to content

Commit 2123869

Browse files
committed
add scenes support
1 parent a0b228c commit 2123869

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

roborock/cli.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,38 @@ async def list_devices(ctx):
113113
click.echo(f"Known devices {device_name_id}")
114114

115115

116+
@click.command()
117+
@click.option("--device_id", required=True)
118+
@click.pass_context
119+
@run_sync()
120+
async def list_scenes(ctx, device_id):
121+
context: RoborockContext = ctx.obj
122+
login_data = context.login_data()
123+
if not login_data.home_data:
124+
await _discover(ctx)
125+
login_data = context.login_data()
126+
client = RoborockApiClient(login_data.email)
127+
scenes = await client.get_scenes(login_data.user_data, device_id)
128+
output_list = []
129+
for scene in scenes:
130+
output_list.append(scene.as_dict())
131+
click.echo(json.dumps(output_list, indent = 4))
132+
133+
134+
@click.command()
135+
@click.option("--scene_id", required=True)
136+
@click.pass_context
137+
@run_sync()
138+
async def execute_scene(ctx, scene_id):
139+
context: RoborockContext = ctx.obj
140+
login_data = context.login_data()
141+
if not login_data.home_data:
142+
await _discover(ctx)
143+
login_data = context.login_data()
144+
client = RoborockApiClient(login_data.email)
145+
await client.execute_scene(login_data.user_data, scene_id)
146+
147+
116148
@click.command()
117149
@click.option("--device_id", required=True)
118150
@click.option("--cmd", required=True)
@@ -192,6 +224,8 @@ def on_package(packet: Packet):
192224
cli.add_command(login)
193225
cli.add_command(discover)
194226
cli.add_command(list_devices)
227+
cli.add_command(list_scenes)
228+
cli.add_command(execute_scene)
195229
cli.add_command(command)
196230
cli.add_command(parser)
197231

roborock/containers.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,11 @@ class HomeDataRoom(RoborockBase):
438438
id: int
439439
name: str
440440

441+
@dataclass
442+
class HomeDataScene(RoborockBase):
443+
id: int
444+
name: str
445+
441446

442447
@dataclass
443448
class HomeData(RoborockBase):

roborock/web_api.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import aiohttp
1212
from aiohttp import ContentTypeError
1313

14-
from roborock.containers import HomeData, HomeDataRoom, ProductResponse, RRiot, UserData
14+
from roborock.containers import HomeData, HomeDataRoom, ProductResponse, RRiot, UserData, HomeDataScene
1515
from roborock.exceptions import (
1616
RoborockAccountDoesNotExist,
1717
RoborockException,
@@ -269,6 +269,46 @@ async def get_rooms(self, user_data: UserData, home_id: int | None = None) -> li
269269
else:
270270
raise RoborockException("home_response result was an unexpected type")
271271

272+
async def get_scenes(self, user_data: UserData, home_id: int) -> list[HomeDataRoom]:
273+
rriot = user_data.rriot
274+
if rriot is None:
275+
raise RoborockException("rriot is none")
276+
if rriot.r.a is None:
277+
raise RoborockException("Missing field 'a' in rriot reference")
278+
scenes_request = PreparedRequest(
279+
rriot.r.a,
280+
{
281+
"Authorization": self._get_hawk_authentication(rriot, f"/user/scene/device/{str(home_id)}"),
282+
},
283+
)
284+
scenes_response = await scenes_request.request("get", f"/user/scene/device/{str(home_id)}")
285+
if not scenes_response.get("success"):
286+
raise RoborockException(scenes_response)
287+
scenes = scenes_response.get("result")
288+
if isinstance(scenes, list):
289+
output_list = []
290+
for scene in scenes:
291+
output_list.append(HomeDataScene.from_dict(scene))
292+
return output_list
293+
else:
294+
raise RoborockException("home_response result was an unexpected type")
295+
296+
async def execute_scene(self, user_data: UserData, scene_id: int) -> list[HomeDataRoom]:
297+
rriot = user_data.rriot
298+
if rriot is None:
299+
raise RoborockException("rriot is none")
300+
if rriot.r.a is None:
301+
raise RoborockException("Missing field 'a' in rriot reference")
302+
execute_scene_request = PreparedRequest(
303+
rriot.r.a,
304+
{
305+
"Authorization": self._get_hawk_authentication(rriot, f"/user/scene/{str(scene_id)}/execute"),
306+
},
307+
)
308+
execute_scene_response = await execute_scene_request.request("post", f"/user/scene/{str(scene_id)}/execute")
309+
if not execute_scene_response.get("success"):
310+
raise RoborockException(execute_scene_response)
311+
272312
async def get_products(self, user_data: UserData) -> ProductResponse:
273313
"""Gets all products and their schemas, good for determining status codes and model numbers."""
274314
base_url = await self._get_base_url()

0 commit comments

Comments
 (0)