aioamazondevices 6.5.3__tar.gz → 8.0.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 (18) hide show
  1. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/PKG-INFO +10 -4
  2. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/README.md +9 -3
  3. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/pyproject.toml +1 -1
  4. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/src/aioamazondevices/__init__.py +1 -1
  5. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/src/aioamazondevices/api.py +54 -138
  6. aioamazondevices-8.0.0/src/aioamazondevices/const/__init__.py +1 -0
  7. aioamazondevices-8.0.0/src/aioamazondevices/const/common.py +26 -0
  8. aioamazondevices-6.5.3/src/aioamazondevices/const.py → aioamazondevices-8.0.0/src/aioamazondevices/const/devices.py +2 -163
  9. aioamazondevices-8.0.0/src/aioamazondevices/const/http.py +36 -0
  10. aioamazondevices-8.0.0/src/aioamazondevices/const/metadata.py +44 -0
  11. aioamazondevices-6.5.3/src/aioamazondevices/query.py → aioamazondevices-8.0.0/src/aioamazondevices/const/queries.py +1 -1
  12. aioamazondevices-8.0.0/src/aioamazondevices/const/schedules.py +61 -0
  13. {aioamazondevices-6.5.3/src/aioamazondevices → aioamazondevices-8.0.0/src/aioamazondevices/const}/sounds.py +2 -1
  14. aioamazondevices-8.0.0/src/aioamazondevices/structures.py +65 -0
  15. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/src/aioamazondevices/utils.py +1 -1
  16. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/LICENSE +0 -0
  17. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/src/aioamazondevices/exceptions.py +0 -0
  18. {aioamazondevices-6.5.3 → aioamazondevices-8.0.0}/src/aioamazondevices/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aioamazondevices
3
- Version: 6.5.3
3
+ Version: 8.0.0
4
4
  Summary: Python library to control Amazon devices
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -81,7 +81,6 @@ The script accept command line arguments or a library_test.json config file:
81
81
  "single_device_name": "Echo Dot Livingroom",
82
82
  "cluster_device_name": "Everywhere",
83
83
  "login_data_file": "out/login_data.json",
84
- "save_raw_data": true,
85
84
  "test": true
86
85
  }
87
86
  ```
@@ -142,6 +141,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
142
141
  <sub><b>Flo</b></sub>
143
142
  </a>
144
143
  </td>
144
+ <td align="center">
145
+ <a href="https://github.com/francescolf">
146
+ <img src="https://avatars.githubusercontent.com/u/14892143?v=4" width="100;" alt="francescolf"/>
147
+ <br />
148
+ <sub><b>Francesco Lo Faro</b></sub>
149
+ </a>
150
+ </td>
151
+ </tr>
152
+ <tr>
145
153
  <td align="center">
146
154
  <a href="https://github.com/lchavezcuu">
147
155
  <img src="https://avatars.githubusercontent.com/u/22165856?v=4" width="100;" alt="lchavezcuu"/>
@@ -149,8 +157,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
149
157
  <sub><b>Luis Chavez</b></sub>
150
158
  </a>
151
159
  </td>
152
- </tr>
153
- <tr>
154
160
  <td align="center">
155
161
  <a href="https://github.com/maxmati">
156
162
  <img src="https://avatars.githubusercontent.com/u/509560?v=4" width="100;" alt="maxmati"/>
@@ -56,7 +56,6 @@ The script accept command line arguments or a library_test.json config file:
56
56
  "single_device_name": "Echo Dot Livingroom",
57
57
  "cluster_device_name": "Everywhere",
58
58
  "login_data_file": "out/login_data.json",
59
- "save_raw_data": true,
60
59
  "test": true
61
60
  }
62
61
  ```
@@ -117,6 +116,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
117
116
  <sub><b>Flo</b></sub>
118
117
  </a>
119
118
  </td>
119
+ <td align="center">
120
+ <a href="https://github.com/francescolf">
121
+ <img src="https://avatars.githubusercontent.com/u/14892143?v=4" width="100;" alt="francescolf"/>
122
+ <br />
123
+ <sub><b>Francesco Lo Faro</b></sub>
124
+ </a>
125
+ </td>
126
+ </tr>
127
+ <tr>
120
128
  <td align="center">
121
129
  <a href="https://github.com/lchavezcuu">
122
130
  <img src="https://avatars.githubusercontent.com/u/22165856?v=4" width="100;" alt="lchavezcuu"/>
@@ -124,8 +132,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
124
132
  <sub><b>Luis Chavez</b></sub>
125
133
  </a>
126
134
  </td>
127
- </tr>
128
- <tr>
129
135
  <td align="center">
130
136
  <a href="https://github.com/maxmati">
131
137
  <img src="https://avatars.githubusercontent.com/u/509560?v=4" width="100;" alt="maxmati"/>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aioamazondevices"
3
- version = "6.5.3"
3
+ version = "8.0.0"
4
4
  requires-python = ">=3.12"
5
5
  description = "Python library to control Amazon devices"
6
6
  authors = [
@@ -1,6 +1,6 @@
1
1
  """aioamazondevices library."""
2
2
 
3
- __version__ = "6.5.3"
3
+ __version__ = "8.0.0"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
@@ -3,15 +3,12 @@
3
3
  import asyncio
4
4
  import base64
5
5
  import hashlib
6
- import mimetypes
7
6
  import secrets
8
7
  import uuid
9
- from dataclasses import dataclass
8
+ from collections.abc import Callable, Coroutine
10
9
  from datetime import UTC, datetime, timedelta
11
- from enum import StrEnum
12
10
  from http import HTTPMethod, HTTPStatus
13
11
  from http.cookies import Morsel
14
- from pathlib import Path
15
12
  from typing import Any, cast
16
13
  from urllib.parse import parse_qs, urlencode
17
14
 
@@ -30,9 +27,13 @@ from multidict import MultiDictProxy
30
27
  from yarl import URL
31
28
 
32
29
  from . import __version__
33
- from .const import (
34
- _LOGGER,
35
- ALEXA_INFO_SKILLS,
30
+ from .const.common import _LOGGER
31
+ from .const.devices import (
32
+ DEVICE_TO_IGNORE,
33
+ DEVICE_TYPE_TO_MODEL,
34
+ SPEAKER_GROUP_FAMILY,
35
+ )
36
+ from .const.http import (
36
37
  AMAZON_APP_BUNDLE_ID,
37
38
  AMAZON_APP_ID,
38
39
  AMAZON_APP_NAME,
@@ -41,33 +42,30 @@ from .const import (
41
42
  AMAZON_DEVICE_SOFTWARE_VERSION,
42
43
  AMAZON_DEVICE_TYPE,
43
44
  ARRAY_WRAPPER,
44
- BIN_EXTENSION,
45
- COUNTRY_GROUPS,
46
45
  CSRF_COOKIE,
47
46
  DEFAULT_HEADERS,
48
47
  DEFAULT_SITE,
49
- DEVICE_TO_IGNORE,
50
- DEVICE_TYPE_TO_MODEL,
51
- HTML_EXTENSION,
52
48
  HTTP_ERROR_199,
53
49
  HTTP_ERROR_299,
54
- JSON_EXTENSION,
55
- NOTIFICATION_ALARM,
56
- NOTIFICATION_MUSIC_ALARM,
57
- NOTIFICATION_REMINDER,
58
- NOTIFICATION_TIMER,
59
- RECURRING_PATTERNS,
60
50
  REFRESH_ACCESS_TOKEN,
61
51
  REFRESH_AUTH_COOKIES,
62
52
  REQUEST_AGENT,
63
- SAVE_PATH,
64
- SENSORS,
65
- SPEAKER_GROUP_FAMILY,
66
53
  URI_DEVICES,
67
54
  URI_DND,
68
55
  URI_NEXUS_GRAPHQL,
69
56
  URI_NOTIFICATIONS,
70
57
  URI_SIGNIN,
58
+ )
59
+ from .const.metadata import ALEXA_INFO_SKILLS, SENSORS
60
+ from .const.queries import QUERY_DEVICE_DATA, QUERY_SENSOR_STATE
61
+ from .const.schedules import (
62
+ COUNTRY_GROUPS,
63
+ NOTIFICATION_ALARM,
64
+ NOTIFICATION_MUSIC_ALARM,
65
+ NOTIFICATION_REMINDER,
66
+ NOTIFICATION_TIMER,
67
+ NOTIFICATIONS_SUPPORTED,
68
+ RECURRING_PATTERNS,
71
69
  WEEKEND_EXCEPTIONS,
72
70
  )
73
71
  from .exceptions import (
@@ -77,70 +75,16 @@ from .exceptions import (
77
75
  CannotRetrieveData,
78
76
  WrongMethod,
79
77
  )
80
- from .query import QUERY_DEVICE_DATA, QUERY_SENSOR_STATE
78
+ from .structures import (
79
+ AmazonDevice,
80
+ AmazonDeviceSensor,
81
+ AmazonMusicSource,
82
+ AmazonSchedule,
83
+ AmazonSequenceType,
84
+ )
81
85
  from .utils import obfuscate_email, scrub_fields
82
86
 
83
87
 
84
- @dataclass
85
- class AmazonDeviceSensor:
86
- """Amazon device sensor class."""
87
-
88
- name: str
89
- value: str | int | float
90
- error: bool
91
- error_type: str | None
92
- error_msg: str | None
93
- scale: str | None
94
-
95
-
96
- @dataclass
97
- class AmazonSchedule:
98
- """Amazon schedule class."""
99
-
100
- type: str # alarm, reminder, timer
101
- status: str
102
- label: str
103
- next_occurrence: datetime | None
104
-
105
-
106
- @dataclass
107
- class AmazonDevice:
108
- """Amazon device class."""
109
-
110
- account_name: str
111
- capabilities: list[str]
112
- device_family: str
113
- device_type: str
114
- device_owner_customer_id: str
115
- household_device: bool
116
- device_cluster_members: list[str]
117
- online: bool
118
- serial_number: str
119
- software_version: str
120
- entity_id: str | None
121
- endpoint_id: str | None
122
- sensors: dict[str, AmazonDeviceSensor]
123
- notifications: dict[str, AmazonSchedule]
124
-
125
-
126
- class AmazonSequenceType(StrEnum):
127
- """Amazon sequence types."""
128
-
129
- Announcement = "AlexaAnnouncement"
130
- Speak = "Alexa.Speak"
131
- Sound = "Alexa.Sound"
132
- Music = "Alexa.Music.PlaySearchPhrase"
133
- TextCommand = "Alexa.TextCommand"
134
- LaunchSkill = "Alexa.Operation.SkillConnections.Launch"
135
-
136
-
137
- class AmazonMusicSource(StrEnum):
138
- """Amazon music sources."""
139
-
140
- Radio = "TUNEIN"
141
- AmazonMusic = "AMAZON_MUSIC"
142
-
143
-
144
88
  class AmazonEchoApi:
145
89
  """Queries Amazon for Echo devices."""
146
90
 
@@ -150,6 +94,8 @@ class AmazonEchoApi:
150
94
  login_email: str,
151
95
  login_password: str,
152
96
  login_data: dict[str, Any] | None = None,
97
+ save_to_file: Callable[[str | dict, str, str], Coroutine[Any, Any, None]]
98
+ | None = None,
153
99
  ) -> None:
154
100
  """Initialize the scanner."""
155
101
  # Check if there is a previous login, otherwise use default (US)
@@ -161,7 +107,7 @@ class AmazonEchoApi:
161
107
  self._login_password = login_password
162
108
 
163
109
  self._cookies = self._build_init_cookies()
164
- self._save_raw_data = False
110
+ self._save_to_file = save_to_file
165
111
  self._login_stored_data = login_data or {}
166
112
  self._serial = self._serial_number()
167
113
  self._account_owner_customer_id: str | None = None
@@ -182,11 +128,6 @@ class AmazonEchoApi:
182
128
  """Return current Amazon domain."""
183
129
  return self._domain
184
130
 
185
- def save_raw_data(self) -> None:
186
- """Save raw data to disk."""
187
- self._save_raw_data = True
188
- _LOGGER.debug("Saving raw data to disk")
189
-
190
131
  def _country_specific_data(self, domain: str) -> None:
191
132
  """Set country specific data."""
192
133
  # Force lower case
@@ -386,6 +327,8 @@ class AmazonEchoApi:
386
327
  headers = DEFAULT_HEADERS.copy()
387
328
  headers.update({"User-Agent": REQUEST_AGENT[agent]})
388
329
  headers.update({"Accept-Language": self._language})
330
+ headers.update({"x-amzn-client": "aioamazondevices"})
331
+ headers.update({"x-amzn-build-version": __version__})
389
332
 
390
333
  if self._csrf_cookie:
391
334
  csrf = {CSRF_COOKIE: self._csrf_cookie}
@@ -462,57 +405,16 @@ class AmazonEchoApi:
462
405
  f"Request failed: {await self._http_phrase_error(resp.status)}"
463
406
  )
464
407
 
465
- await self._save_to_file(
466
- await resp.text(),
467
- url,
468
- mimetypes.guess_extension(content_type.split(";")[0]) or ".raw",
469
- )
470
-
471
- return BeautifulSoup(await resp.read() or "", "html.parser"), resp
472
-
473
- async def _save_to_file(
474
- self,
475
- raw_data: str | dict,
476
- url: str,
477
- extension: str = HTML_EXTENSION,
478
- output_path: str = SAVE_PATH,
479
- ) -> None:
480
- """Save response data to disk."""
481
- if not self._save_raw_data or not raw_data:
482
- return
483
-
484
- output_dir = Path(output_path)
485
- output_dir.mkdir(parents=True, exist_ok=True)
486
-
487
- if url.startswith("http"):
488
- url_split = url.split("/")
489
- base_filename = f"{url_split[3]}-{url_split[4].split('?')[0]}"
490
- else:
491
- base_filename = url
492
- fullpath = Path(output_dir, base_filename + extension)
493
-
494
- data: str
495
- if isinstance(raw_data, dict):
496
- data = orjson.dumps(raw_data, option=orjson.OPT_INDENT_2).decode("utf-8")
497
- elif extension in [HTML_EXTENSION, BIN_EXTENSION]:
498
- data = raw_data
499
- else:
500
- data = orjson.dumps(
501
- orjson.loads(raw_data),
502
- option=orjson.OPT_INDENT_2,
503
- ).decode("utf-8")
504
-
505
- i = 2
506
- while fullpath.exists():
507
- filename = f"{base_filename}_{i!s}{extension}"
508
- fullpath = Path(output_dir, filename)
509
- i += 1
408
+ raw_content = await resp.read()
510
409
 
511
- _LOGGER.warning("Saving data to %s", fullpath)
410
+ if self._save_to_file:
411
+ await self._save_to_file(
412
+ raw_content.decode("utf-8"),
413
+ url,
414
+ content_type,
415
+ )
512
416
 
513
- with Path.open(fullpath, mode="w", encoding="utf-8") as file:
514
- file.write(data)
515
- file.write("\n")
417
+ return BeautifulSoup(raw_content or "", "html.parser"), resp
516
418
 
517
419
  async def _register_device(
518
420
  self,
@@ -612,6 +514,9 @@ class AmazonEchoApi:
612
514
  """Retrieve devices sensors states."""
613
515
  devices_sensors: dict[str, dict[str, AmazonDeviceSensor]] = {}
614
516
 
517
+ if not self._endpoints:
518
+ return {}
519
+
615
520
  endpoint_ids = list(self._endpoints.keys())
616
521
  payload = [
617
522
  {
@@ -793,6 +698,18 @@ class AmazonEchoApi:
793
698
  for schedule in notifications["notifications"]:
794
699
  schedule_type: str = schedule["type"]
795
700
  schedule_device_serial = schedule["deviceSerialNumber"]
701
+
702
+ if schedule_device_serial in DEVICE_TO_IGNORE:
703
+ continue
704
+
705
+ if schedule_type not in NOTIFICATIONS_SUPPORTED:
706
+ _LOGGER.debug(
707
+ "Unsupported schedule type %s for device %s",
708
+ schedule_type,
709
+ schedule_device_serial,
710
+ )
711
+ continue
712
+
796
713
  if schedule_type == NOTIFICATION_MUSIC_ALARM:
797
714
  # Structure is the same as standard Alarm
798
715
  schedule_type = NOTIFICATION_ALARM
@@ -959,7 +876,6 @@ class AmazonEchoApi:
959
876
  await self._domain_refresh_auth_cookies()
960
877
 
961
878
  self._login_stored_data.update({"site": f"https://www.amazon.{self._domain}"})
962
- await self._save_to_file(self._login_stored_data, "login_data", JSON_EXTENSION)
963
879
 
964
880
  # Can take a little while to register device but we need it
965
881
  # to be able to pickout account customer ID
@@ -0,0 +1 @@
1
+ """aioamazondevices const package."""
@@ -0,0 +1,26 @@
1
+ """aioamazondevices Common const."""
2
+
3
+ import logging
4
+
5
+ _LOGGER = logging.getLogger(__package__)
6
+
7
+ TO_REDACT = {
8
+ "address",
9
+ "address1",
10
+ "address2",
11
+ "address3",
12
+ "city",
13
+ "county",
14
+ "customerId",
15
+ "deviceAccountId",
16
+ "deviceAddress",
17
+ "deviceOwnerCustomerId",
18
+ "given_name",
19
+ "name",
20
+ "password",
21
+ "postalCode",
22
+ "searchCustomerId",
23
+ "state",
24
+ "street",
25
+ "user_id",
26
+ }
@@ -1,117 +1,10 @@
1
- """Constants for Amazon devices."""
1
+ """aioamazondevices devices."""
2
2
 
3
- import logging
4
-
5
- _LOGGER = logging.getLogger(__package__)
6
-
7
- ARRAY_WRAPPER = "generatedArrayWrapper"
8
-
9
- HTTP_ERROR_199 = 199
10
- HTTP_ERROR_299 = 299
11
-
12
- TO_REDACT = {
13
- "address",
14
- "address1",
15
- "address2",
16
- "address3",
17
- "city",
18
- "county",
19
- "customerId",
20
- "deviceAccountId",
21
- "deviceAddress",
22
- "deviceOwnerCustomerId",
23
- "given_name",
24
- "name",
25
- "password",
26
- "postalCode",
27
- "searchCustomerId",
28
- "state",
29
- "street",
30
- "user_id",
31
- }
32
-
33
- # Amazon APP info
34
- AMAZON_APP_BUNDLE_ID = "com.amazon.echo"
35
- AMAZON_APP_ID = "MAPiOSLib/6.0/ToHideRetailLink"
36
- AMAZON_APP_NAME = "AioAmazonDevices"
37
- AMAZON_APP_VERSION = "2.2.663733.0"
38
- AMAZON_DEVICE_SOFTWARE_VERSION = "35602678"
39
- AMAZON_DEVICE_TYPE = "A2IVLV5VM2W81"
40
- AMAZON_CLIENT_OS = "18.5"
41
-
42
- DEFAULT_SITE = "https://www.amazon.com"
43
- DEFAULT_HEADERS = {
44
- "Accept-Charset": "utf-8",
45
- "Accept-Encoding": "gzip",
46
- "Connection": "keep-alive",
47
- }
48
- CSRF_COOKIE = "csrf"
49
- REQUEST_AGENT = {
50
- "Amazon": f"AmazonWebView/AmazonAlexa/{AMAZON_APP_VERSION}/iOS/{AMAZON_CLIENT_OS}/iPhone", # noqa: E501
51
- "Browser": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0", # noqa: E501
52
- }
53
-
54
- REFRESH_ACCESS_TOKEN = "access_token" # noqa: S105
55
- REFRESH_AUTH_COOKIES = "auth_cookies"
56
-
57
- URI_DEVICES = "/api/devices-v2/device"
58
- URI_DND = "/api/dnd/device-status-list"
59
- URI_NOTIFICATIONS = "/api/notifications"
60
- URI_SIGNIN = "/ap/signin"
61
- URI_NEXUS_GRAPHQL = "/nexus/v1/graphql"
62
-
63
- SENSOR_STATE_OFF = "NOT_DETECTED"
64
-
65
- # File extensions
66
- SAVE_PATH = "out"
67
- HTML_EXTENSION = ".html"
68
- JSON_EXTENSION = ".json"
69
- BIN_EXTENSION = ".bin"
3
+ from .http import AMAZON_DEVICE_TYPE
70
4
 
71
5
  SPEAKER_GROUP_FAMILY = "WHA"
72
6
  SPEAKER_GROUP_MODEL = "Speaker Group"
73
7
 
74
- SENSORS: dict[str, dict[str, str | None]] = {
75
- "temperatureSensor": {
76
- "name": "temperature",
77
- "key": "value",
78
- "subkey": "value",
79
- "scale": "scale",
80
- },
81
- "motionSensor": {
82
- "name": "detectionState",
83
- "key": "detectionStateValue",
84
- "subkey": None,
85
- "scale": None,
86
- },
87
- "lightSensor": {
88
- "name": "illuminance",
89
- "key": "illuminanceValue",
90
- "subkey": "value",
91
- "scale": None,
92
- },
93
- }
94
-
95
- ALEXA_INFO_SKILLS = [
96
- "Alexa.Calendar.PlayToday",
97
- "Alexa.Calendar.PlayTomorrow",
98
- "Alexa.Calendar.PlayNext",
99
- "Alexa.Date.Play",
100
- "Alexa.Time.Play",
101
- "Alexa.News.NationalNews",
102
- "Alexa.FlashBriefing.Play",
103
- "Alexa.Traffic.Play",
104
- "Alexa.Weather.Play",
105
- "Alexa.CleanUp.Play",
106
- "Alexa.GoodMorning.Play",
107
- "Alexa.SingASong.Play",
108
- "Alexa.FunFact.Play",
109
- "Alexa.Joke.Play",
110
- "Alexa.TellStory.Play",
111
- "Alexa.ImHome.Play",
112
- "Alexa.GoodNight.Play",
113
- ]
114
-
115
8
  DEVICE_TO_IGNORE: list[str] = [
116
9
  AMAZON_DEVICE_TYPE, # Alexa App for iOS
117
10
  "A2TF17PFR55MTB", # Alexa App for Android
@@ -480,57 +373,3 @@ DEVICE_TYPE_TO_MODEL: dict[str, dict[str, str | None]] = {
480
373
  "hw_version": "Gen2",
481
374
  },
482
375
  }
483
-
484
- RECURRING_PATTERNS: dict[str, str] = {
485
- "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
486
- "XXXX-WE": "FREQ=WEEKLY;BYDAY=SA,SU",
487
- "XXXX-WXX-1": "FREQ=WEEKLY;BYDAY=MO",
488
- "XXXX-WXX-2": "FREQ=WEEKLY;BYDAY=TU",
489
- "XXXX-WXX-3": "FREQ=WEEKLY;BYDAY=WE",
490
- "XXXX-WXX-4": "FREQ=WEEKLY;BYDAY=TH",
491
- "XXXX-WXX-5": "FREQ=WEEKLY;BYDAY=FR",
492
- "XXXX-WXX-6": "FREQ=WEEKLY;BYDAY=SA",
493
- "XXXX-WXX-7": "FREQ=WEEKLY;BYDAY=SU",
494
- }
495
-
496
- WEEKEND_EXCEPTIONS = {
497
- "TH-FR": {
498
- "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,SA,SU",
499
- "XXXX-WE": "FREQ=WEEKLY;BYDAY=TH,FR",
500
- },
501
- "FR-SA": {
502
- "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,SU",
503
- "XXXX-WE": "FREQ=WEEKLY;BYDAY=FR,SA",
504
- },
505
- }
506
-
507
- # Countries grouped by their weekend type
508
- COUNTRY_GROUPS = {
509
- "TH-FR": ["IR"],
510
- "FR-SA": [
511
- "AF",
512
- "BD",
513
- "BH",
514
- "DZ",
515
- "EG",
516
- "IL",
517
- "IQ",
518
- "JO",
519
- "KW",
520
- "LY",
521
- "MV",
522
- "MY",
523
- "OM",
524
- "PS",
525
- "QA",
526
- "SA",
527
- "SD",
528
- "SY",
529
- "YE",
530
- ],
531
- }
532
-
533
- NOTIFICATION_ALARM = "Alarm"
534
- NOTIFICATION_MUSIC_ALARM = "MusicAlarm"
535
- NOTIFICATION_REMINDER = "Reminder"
536
- NOTIFICATION_TIMER = "Timer"
@@ -0,0 +1,36 @@
1
+ """aioamazondevices HTTP const."""
2
+
3
+ HTTP_ERROR_199 = 199
4
+ HTTP_ERROR_299 = 299
5
+
6
+ ARRAY_WRAPPER = "generatedArrayWrapper"
7
+
8
+ # Amazon APP info
9
+ AMAZON_APP_BUNDLE_ID = "com.amazon.echo"
10
+ AMAZON_APP_ID = "MAPiOSLib/6.0/ToHideRetailLink"
11
+ AMAZON_APP_NAME = "AioAmazonDevices"
12
+ AMAZON_APP_VERSION = "2.2.663733.0"
13
+ AMAZON_DEVICE_SOFTWARE_VERSION = "35602678"
14
+ AMAZON_DEVICE_TYPE = "A2IVLV5VM2W81"
15
+ AMAZON_CLIENT_OS = "18.5"
16
+
17
+ DEFAULT_SITE = "https://www.amazon.com"
18
+ DEFAULT_HEADERS = {
19
+ "Accept-Charset": "utf-8",
20
+ "Accept-Encoding": "gzip",
21
+ "Connection": "keep-alive",
22
+ }
23
+ CSRF_COOKIE = "csrf"
24
+ REQUEST_AGENT = {
25
+ "Amazon": f"AmazonWebView/AmazonAlexa/{AMAZON_APP_VERSION}/iOS/{AMAZON_CLIENT_OS}/iPhone", # noqa: E501
26
+ "Browser": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0", # noqa: E501
27
+ }
28
+
29
+ REFRESH_ACCESS_TOKEN = "access_token" # noqa: S105
30
+ REFRESH_AUTH_COOKIES = "auth_cookies"
31
+
32
+ URI_DEVICES = "/api/devices-v2/device"
33
+ URI_DND = "/api/dnd/device-status-list"
34
+ URI_NOTIFICATIONS = "/api/notifications"
35
+ URI_SIGNIN = "/ap/signin"
36
+ URI_NEXUS_GRAPHQL = "/nexus/v1/graphql"
@@ -0,0 +1,44 @@
1
+ """aioamazondevices Additional entities const."""
2
+
3
+ SENSOR_STATE_OFF = "NOT_DETECTED"
4
+
5
+ SENSORS: dict[str, dict[str, str | None]] = {
6
+ "temperatureSensor": {
7
+ "name": "temperature",
8
+ "key": "value",
9
+ "subkey": "value",
10
+ "scale": "scale",
11
+ },
12
+ "motionSensor": {
13
+ "name": "detectionState",
14
+ "key": "detectionStateValue",
15
+ "subkey": None,
16
+ "scale": None,
17
+ },
18
+ "lightSensor": {
19
+ "name": "illuminance",
20
+ "key": "illuminanceValue",
21
+ "subkey": "value",
22
+ "scale": None,
23
+ },
24
+ }
25
+
26
+ ALEXA_INFO_SKILLS = [
27
+ "Alexa.Calendar.PlayToday",
28
+ "Alexa.Calendar.PlayTomorrow",
29
+ "Alexa.Calendar.PlayNext",
30
+ "Alexa.Date.Play",
31
+ "Alexa.Time.Play",
32
+ "Alexa.News.NationalNews",
33
+ "Alexa.FlashBriefing.Play",
34
+ "Alexa.Traffic.Play",
35
+ "Alexa.Weather.Play",
36
+ "Alexa.CleanUp.Play",
37
+ "Alexa.GoodMorning.Play",
38
+ "Alexa.SingASong.Play",
39
+ "Alexa.FunFact.Play",
40
+ "Alexa.Joke.Play",
41
+ "Alexa.TellStory.Play",
42
+ "Alexa.ImHome.Play",
43
+ "Alexa.GoodNight.Play",
44
+ ]
@@ -1,4 +1,4 @@
1
- """GraphQL Queries."""
1
+ """aioamazondevices GraphQL queries."""
2
2
 
3
3
  QUERY_DEVICE_DATA = """
4
4
  query getDevicesBaseData {
@@ -0,0 +1,61 @@
1
+ """aioamazondevices: schedules."""
2
+
3
+ NOTIFICATION_ALARM = "Alarm"
4
+ NOTIFICATION_MUSIC_ALARM = "MusicAlarm"
5
+ NOTIFICATION_REMINDER = "Reminder"
6
+ NOTIFICATION_TIMER = "Timer"
7
+ NOTIFICATIONS_SUPPORTED = [
8
+ NOTIFICATION_ALARM,
9
+ NOTIFICATION_MUSIC_ALARM,
10
+ NOTIFICATION_REMINDER,
11
+ NOTIFICATION_TIMER,
12
+ ]
13
+
14
+ RECURRING_PATTERNS: dict[str, str] = {
15
+ "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR",
16
+ "XXXX-WE": "FREQ=WEEKLY;BYDAY=SA,SU",
17
+ "XXXX-WXX-1": "FREQ=WEEKLY;BYDAY=MO",
18
+ "XXXX-WXX-2": "FREQ=WEEKLY;BYDAY=TU",
19
+ "XXXX-WXX-3": "FREQ=WEEKLY;BYDAY=WE",
20
+ "XXXX-WXX-4": "FREQ=WEEKLY;BYDAY=TH",
21
+ "XXXX-WXX-5": "FREQ=WEEKLY;BYDAY=FR",
22
+ "XXXX-WXX-6": "FREQ=WEEKLY;BYDAY=SA",
23
+ "XXXX-WXX-7": "FREQ=WEEKLY;BYDAY=SU",
24
+ }
25
+
26
+ WEEKEND_EXCEPTIONS = {
27
+ "TH-FR": {
28
+ "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,SA,SU",
29
+ "XXXX-WE": "FREQ=WEEKLY;BYDAY=TH,FR",
30
+ },
31
+ "FR-SA": {
32
+ "XXXX-WD": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,SU",
33
+ "XXXX-WE": "FREQ=WEEKLY;BYDAY=FR,SA",
34
+ },
35
+ }
36
+
37
+ # Countries grouped by their weekend type
38
+ COUNTRY_GROUPS = {
39
+ "TH-FR": ["IR"],
40
+ "FR-SA": [
41
+ "AF",
42
+ "BD",
43
+ "BH",
44
+ "DZ",
45
+ "EG",
46
+ "IL",
47
+ "IQ",
48
+ "JO",
49
+ "KW",
50
+ "LY",
51
+ "MV",
52
+ "MY",
53
+ "OM",
54
+ "PS",
55
+ "QA",
56
+ "SA",
57
+ "SD",
58
+ "SY",
59
+ "YE",
60
+ ],
61
+ }
@@ -1,4 +1,5 @@
1
- """Generated by update_sounds_list.py [2025-08-28 15:45]."""
1
+ """aioamazondevices sounds."""
2
+ # Generated by update_sounds_list.py [2025-10-23 10:03].
2
3
 
3
4
  SOUNDS_LIST = {
4
5
  "air_horn_03": "Air horn",
@@ -0,0 +1,65 @@
1
+ """aioamazondevices structures module."""
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from enum import StrEnum
6
+
7
+
8
+ @dataclass
9
+ class AmazonDeviceSensor:
10
+ """Amazon device sensor class."""
11
+
12
+ name: str
13
+ value: str | int | float
14
+ error: bool
15
+ error_type: str | None
16
+ error_msg: str | None
17
+ scale: str | None
18
+
19
+
20
+ @dataclass
21
+ class AmazonSchedule:
22
+ """Amazon schedule class."""
23
+
24
+ type: str # alarm, reminder, timer
25
+ status: str
26
+ label: str
27
+ next_occurrence: datetime | None
28
+
29
+
30
+ @dataclass
31
+ class AmazonDevice:
32
+ """Amazon device class."""
33
+
34
+ account_name: str
35
+ capabilities: list[str]
36
+ device_family: str
37
+ device_type: str
38
+ device_owner_customer_id: str
39
+ household_device: bool
40
+ device_cluster_members: list[str]
41
+ online: bool
42
+ serial_number: str
43
+ software_version: str
44
+ entity_id: str | None
45
+ endpoint_id: str | None
46
+ sensors: dict[str, AmazonDeviceSensor]
47
+ notifications: dict[str, AmazonSchedule]
48
+
49
+
50
+ class AmazonSequenceType(StrEnum):
51
+ """Amazon sequence types."""
52
+
53
+ Announcement = "AlexaAnnouncement"
54
+ Speak = "Alexa.Speak"
55
+ Sound = "Alexa.Sound"
56
+ Music = "Alexa.Music.PlaySearchPhrase"
57
+ TextCommand = "Alexa.TextCommand"
58
+ LaunchSkill = "Alexa.Operation.SkillConnections.Launch"
59
+
60
+
61
+ class AmazonMusicSource(StrEnum):
62
+ """Amazon music sources."""
63
+
64
+ Radio = "TUNEIN"
65
+ AmazonMusic = "AMAZON_MUSIC"
@@ -3,7 +3,7 @@
3
3
  from collections.abc import Collection
4
4
  from typing import Any
5
5
 
6
- from .const import TO_REDACT
6
+ from .const.common import TO_REDACT
7
7
 
8
8
 
9
9
  def obfuscate_email(email: str) -> str: