python-roborock 2.10.1__tar.gz → 2.11.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {python_roborock-2.10.1 → python_roborock-2.11.0}/PKG-INFO +1 -1
  2. {python_roborock-2.10.1 → python_roborock-2.11.0}/pyproject.toml +1 -1
  3. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/cli.py +34 -0
  4. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/containers.py +6 -0
  5. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/web_api.py +38 -1
  6. {python_roborock-2.10.1 → python_roborock-2.11.0}/LICENSE +0 -0
  7. {python_roborock-2.10.1 → python_roborock-2.11.0}/README.md +0 -0
  8. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/__init__.py +0 -0
  9. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/api.py +0 -0
  10. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/cloud_api.py +0 -0
  11. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/code_mappings.py +0 -0
  12. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/command_cache.py +0 -0
  13. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/const.py +0 -0
  14. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/exceptions.py +0 -0
  15. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/local_api.py +0 -0
  16. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/protocol.py +0 -0
  17. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/py.typed +0 -0
  18. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/roborock_future.py +0 -0
  19. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/roborock_message.py +0 -0
  20. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/roborock_typing.py +0 -0
  21. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/util.py +0 -0
  22. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_1_apis/__init__.py +0 -0
  23. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_1_apis/roborock_client_v1.py +0 -0
  24. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_1_apis/roborock_local_client_v1.py +0 -0
  25. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_1_apis/roborock_mqtt_client_v1.py +0 -0
  26. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_a01_apis/__init__.py +0 -0
  27. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_a01_apis/roborock_client_a01.py +0 -0
  28. {python_roborock-2.10.1 → python_roborock-2.11.0}/roborock/version_a01_apis/roborock_mqtt_client_a01.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: python-roborock
3
- Version: 2.10.1
3
+ Version: 2.11.0
4
4
  Summary: A package to control Roborock vacuums.
5
5
  License: GPL-3.0-only
6
6
  Keywords: roborock,vacuum,homeassistant
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-roborock"
3
- version = "2.10.1"
3
+ version = "2.11.0"
4
4
  description = "A package to control Roborock vacuums."
5
5
  authors = ["humbertogontijo <humbertogontijo@users.noreply.github.com>"]
6
6
  license = "GPL-3.0-only"
@@ -113,6 +113,38 @@ async def list_devices(ctx):
113
113
  click.echo(f"Known devices {device_name_id}")
114
114
 
115
115
 
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
+
116
148
  @click.command()
117
149
  @click.option("--device_id", required=True)
118
150
  @click.option("--cmd", required=True)
@@ -192,6 +224,8 @@ async def parser(_, local_key, device_ip, file):
192
224
  cli.add_command(login)
193
225
  cli.add_command(discover)
194
226
  cli.add_command(list_devices)
227
+ cli.add_command(list_scenes)
228
+ cli.add_command(execute_scene)
195
229
  cli.add_command(command)
196
230
  cli.add_command(parser)
197
231
 
@@ -439,6 +439,12 @@ class HomeDataRoom(RoborockBase):
439
439
  name: str
440
440
 
441
441
 
442
+ @dataclass
443
+ class HomeDataScene(RoborockBase):
444
+ id: int
445
+ name: str
446
+
447
+
442
448
  @dataclass
443
449
  class HomeData(RoborockBase):
444
450
  id: int
@@ -11,7 +11,7 @@ import time
11
11
  import aiohttp
12
12
  from aiohttp import ContentTypeError, FormData
13
13
 
14
- from roborock.containers import HomeData, HomeDataRoom, ProductResponse, RRiot, UserData
14
+ from roborock.containers import HomeData, HomeDataRoom, HomeDataScene, ProductResponse, RRiot, UserData
15
15
  from roborock.exceptions import (
16
16
  RoborockAccountDoesNotExist,
17
17
  RoborockException,
@@ -355,6 +355,43 @@ class RoborockApiClient:
355
355
  else:
356
356
  raise RoborockException("home_response result was an unexpected type")
357
357
 
358
+ async def get_scenes(self, user_data: UserData, device_id: int) -> list[HomeDataScene]:
359
+ rriot = user_data.rriot
360
+ if rriot is None:
361
+ raise RoborockException("rriot is none")
362
+ if rriot.r.a is None:
363
+ raise RoborockException("Missing field 'a' in rriot reference")
364
+ scenes_request = PreparedRequest(
365
+ rriot.r.a,
366
+ {
367
+ "Authorization": self._get_hawk_authentication(rriot, f"/user/scene/device/{str(device_id)}"),
368
+ },
369
+ )
370
+ scenes_response = await scenes_request.request("get", f"/user/scene/device/{str(device_id)}")
371
+ if not scenes_response.get("success"):
372
+ raise RoborockException(scenes_response)
373
+ scenes = scenes_response.get("result")
374
+ if isinstance(scenes, list):
375
+ return [HomeDataScene.from_dict(scene) for scene in scenes]
376
+ else:
377
+ raise RoborockException("scene_response result was an unexpected type")
378
+
379
+ async def execute_scene(self, user_data: UserData, scene_id: int) -> None:
380
+ rriot = user_data.rriot
381
+ if rriot is None:
382
+ raise RoborockException("rriot is none")
383
+ if rriot.r.a is None:
384
+ raise RoborockException("Missing field 'a' in rriot reference")
385
+ execute_scene_request = PreparedRequest(
386
+ rriot.r.a,
387
+ {
388
+ "Authorization": self._get_hawk_authentication(rriot, f"/user/scene/{str(scene_id)}/execute"),
389
+ },
390
+ )
391
+ execute_scene_response = await execute_scene_request.request("POST", f"/user/scene/{str(scene_id)}/execute")
392
+ if not execute_scene_response.get("success"):
393
+ raise RoborockException(execute_scene_response)
394
+
358
395
  async def get_products(self, user_data: UserData) -> ProductResponse:
359
396
  """Gets all products and their schemas, good for determining status codes and model numbers."""
360
397
  base_url = await self._get_base_url()