aioamazondevices 6.2.9__py3-none-any.whl → 6.4.0__py3-none-any.whl

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.

Potentially problematic release.


This version of aioamazondevices might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  """aioamazondevices library."""
2
2
 
3
- __version__ = "6.2.9"
3
+ __version__ = "6.4.0"
4
4
 
5
5
 
6
6
  from .api import AmazonDevice, AmazonEchoApi
aioamazondevices/api.py CHANGED
@@ -53,6 +53,7 @@ from .const import (
53
53
  SAVE_PATH,
54
54
  SENSORS,
55
55
  URI_DEVICES,
56
+ URI_DND,
56
57
  URI_NEXUS_GRAPHQL,
57
58
  URI_SIGNIN,
58
59
  )
@@ -63,7 +64,7 @@ from .exceptions import (
63
64
  CannotRetrieveData,
64
65
  WrongMethod,
65
66
  )
66
- from .query import QUERY_DEVICE_STATE
67
+ from .query import QUERY_DEVICE_DATA, QUERY_SENSOR_STATE
67
68
  from .utils import obfuscate_email, scrub_fields
68
69
 
69
70
 
@@ -74,6 +75,8 @@ class AmazonDeviceSensor:
74
75
  name: str
75
76
  value: str | int | float
76
77
  error: bool
78
+ error_type: str | None
79
+ error_msg: str | None
77
80
  scale: str | None
78
81
 
79
82
 
@@ -141,6 +144,12 @@ class AmazonEchoApi:
141
144
  self._list_for_clusters: dict[str, str] = {}
142
145
 
143
146
  self._session = client_session
147
+ self._final_devices: dict[str, AmazonDevice] = {}
148
+ self._endpoints: dict[str, str] = {} # endpoint ID to serial number map
149
+
150
+ initial_time = datetime.now(UTC) - timedelta(days=2) # force initial refresh
151
+ self._last_devices_refresh: datetime = initial_time
152
+ self._last_endpoint_refresh: datetime = initial_time
144
153
 
145
154
  _LOGGER.debug("Initialize library v%s", __version__)
146
155
 
@@ -336,7 +345,7 @@ class AmazonEchoApi:
336
345
  self,
337
346
  method: str,
338
347
  url: str,
339
- input_data: dict[str, Any] | None = None,
348
+ input_data: dict[str, Any] | list[dict[str, Any]] | None = None,
340
349
  json_data: bool = False,
341
350
  ) -> tuple[BeautifulSoup, ClientResponse]:
342
351
  """Return request response context data."""
@@ -572,17 +581,21 @@ class AmazonEchoApi:
572
581
  _LOGGER.info("Register device: %s", scrub_fields(login_data))
573
582
  return login_data
574
583
 
575
- async def _get_devices_state(
576
- self,
577
- ) -> dict[str, Any]:
578
- """Get Device State."""
579
- payload = {
580
- "operationName": "getDevicesState",
581
- "variables": {
582
- "latencyTolerance": "LOW",
583
- },
584
- "query": QUERY_DEVICE_STATE,
585
- }
584
+ async def _get_sensors_state(
585
+ self, endpoint_id_list: list[str]
586
+ ) -> dict[str, Any] | list[dict[str, Any]]:
587
+ """Get sensor State."""
588
+ payload = [
589
+ {
590
+ "operationName": "getEndpointState",
591
+ "variables": {
592
+ "endpointId": endpoint_id,
593
+ "latencyTolerance": "LOW",
594
+ },
595
+ "query": QUERY_SENSOR_STATE,
596
+ }
597
+ for endpoint_id in endpoint_id_list
598
+ ]
586
599
 
587
600
  _, raw_resp = await self._session_request(
588
601
  method=HTTPMethod.POST,
@@ -593,52 +606,52 @@ class AmazonEchoApi:
593
606
 
594
607
  return await self._response_to_json(raw_resp)
595
608
 
596
- async def _get_sensors_states(
597
- self, devices: dict[str, Any]
598
- ) -> tuple[dict[str, dict[str, Any]], dict[str, dict[str, AmazonDeviceSensor]]]:
609
+ async def _get_sensors_states(self) -> dict[str, dict[str, AmazonDeviceSensor]]:
599
610
  """Retrieve devices sensors states."""
600
- devices_state = await self._get_devices_state()
601
611
  devices_sensors: dict[str, dict[str, AmazonDeviceSensor]] = {}
602
- devices_endpoints: dict[str, dict[str, Any]] = {}
603
-
604
- if error := devices_state.get("errors"):
605
- if isinstance(error, list):
606
- error = error[0]
607
- msg = error.get("message", "Unknown error")
608
- path = error.get("path", "Unknown path")
609
- _LOGGER.error("Error retrieving devices state: %s for path %s", msg, path)
610
- return {}, {}
611
-
612
- if not (data := devices_state.get("data")) or not data.get("listEndpoints"):
613
- _LOGGER.error("Malformed devices state data received: %s", devices_state)
614
- return {}, {}
615
612
 
616
- endpoints = data["listEndpoints"]
617
- for endpoint in endpoints.get("endpoints"):
618
- serial_number = (
619
- endpoint["serialNumber"]["value"]["text"]
620
- if endpoint["serialNumber"]
621
- else None
622
- )
623
- if serial_number in devices:
624
- devices_sensors[serial_number] = self._get_device_sensor_state(
625
- endpoint, serial_number
613
+ # batch endpoints into groups of 3 to reduce number of requests
614
+ endpoint_ids = list(self._endpoints.keys())
615
+ batches = [endpoint_ids[i : i + 3] for i in range(0, len(endpoint_ids), 3)]
616
+ for endpoint_id_batch in batches:
617
+ sensors_state = await self._get_sensors_state(endpoint_id_batch)
618
+ _LOGGER.debug("Sensor data - %s", sensors_state)
619
+
620
+ if not isinstance(sensors_state, list) and (
621
+ error := sensors_state.get("errors")
622
+ ):
623
+ if isinstance(error, list):
624
+ error = error[0]
625
+ msg = error.get("message", "Unknown error")
626
+ path = error.get("path", "Unknown path")
627
+ _LOGGER.error(
628
+ "Error retrieving devices state: %s for path %s", msg, path
626
629
  )
627
- devices_endpoints[serial_number] = endpoint
628
-
629
- return devices_endpoints, devices_sensors
630
+ return {}
631
+
632
+ for endpoint_data in sensors_state:
633
+ if (
634
+ not isinstance(endpoint_data, dict)
635
+ or not (data := endpoint_data.get("data"))
636
+ or not (endpoint := data.get("endpoint"))
637
+ ):
638
+ _LOGGER.error(
639
+ "Malformed sensor state data received: %s", endpoint_data
640
+ )
641
+ return {}
642
+ serial_number = self._endpoints[endpoint.get("endpointId")]
643
+
644
+ if serial_number in self._final_devices:
645
+ devices_sensors[serial_number] = self._get_device_sensor_state(
646
+ endpoint, serial_number
647
+ )
648
+
649
+ return devices_sensors
630
650
 
631
651
  def _get_device_sensor_state(
632
652
  self, endpoint: dict[str, Any], serial_number: str
633
653
  ) -> dict[str, AmazonDeviceSensor]:
634
654
  device_sensors: dict[str, AmazonDeviceSensor] = {}
635
- if endpoint_dnd := endpoint.get("settings", {}).get("doNotDisturb"):
636
- device_sensors["dnd"] = AmazonDeviceSensor(
637
- name="dnd",
638
- value=endpoint_dnd.get("toggleValue"),
639
- error=bool(endpoint_dnd.get("error")),
640
- scale=None,
641
- )
642
655
  for feature in endpoint.get("features", {}):
643
656
  if (sensor_template := SENSORS.get(feature["name"])) is None:
644
657
  # Skip sensors that are not in the predefined list
@@ -653,7 +666,11 @@ class AmazonEchoApi:
653
666
 
654
667
  value: str | int | float = "n/a"
655
668
  scale: str | None = None
656
- error = bool(feature_property.get("error"))
669
+
670
+ api_error = feature_property.get("error", {})
671
+ error = bool(api_error)
672
+ error_type = api_error.get("type")
673
+ error_msg = api_error.get("message")
657
674
  if not error:
658
675
  try:
659
676
  value_raw = feature_property[sensor_template["key"]]
@@ -683,15 +700,56 @@ class AmazonEchoApi:
683
700
  feature_property,
684
701
  repr(exc),
685
702
  )
703
+ if error:
704
+ _LOGGER.debug(
705
+ "error in sensor %s - %s - %s", name, error_type, error_msg
706
+ )
686
707
  device_sensors[name] = AmazonDeviceSensor(
687
708
  name,
688
709
  value,
689
710
  error,
711
+ error_type,
712
+ error_msg,
690
713
  scale,
691
714
  )
692
715
 
693
716
  return device_sensors
694
717
 
718
+ async def _get_devices_endpoint_data(self) -> dict[str, dict[str, Any]]:
719
+ """Get Devices endpoint data."""
720
+ payload = {
721
+ "operationName": "getDevicesBaseData",
722
+ "query": QUERY_DEVICE_DATA,
723
+ }
724
+
725
+ _, raw_resp = await self._session_request(
726
+ method=HTTPMethod.POST,
727
+ url=f"https://alexa.amazon.{self._domain}{URI_NEXUS_GRAPHQL}",
728
+ input_data=payload,
729
+ json_data=True,
730
+ )
731
+
732
+ endpoint_data = await self._response_to_json(raw_resp)
733
+
734
+ if not (data := endpoint_data.get("data")) or not data.get("listEndpoints"):
735
+ _LOGGER.error("Malformed endpoint data received: %s", endpoint_data)
736
+ return {}
737
+
738
+ endpoints = data["listEndpoints"]
739
+ devices_endpoints: dict[str, dict[str, Any]] = {}
740
+ for endpoint in endpoints.get("endpoints"):
741
+ # save looking up sensor data on apps
742
+ if endpoint.get("alexaEnabledMetadata", {}).get("category") == "APP":
743
+ continue
744
+
745
+ if endpoint.get("serialNumber"):
746
+ serial_number = endpoint["serialNumber"]["value"]["text"]
747
+ devices_endpoints[serial_number] = endpoint
748
+ self._endpoints[endpoint["endpointId"]] = serial_number
749
+
750
+ self._last_endpoint_refresh = datetime.now(UTC)
751
+ return devices_endpoints
752
+
695
753
  async def _response_to_json(self, raw_resp: ClientResponse) -> dict[str, Any]:
696
754
  """Convert response to JSON, if possible."""
697
755
  try:
@@ -868,7 +926,51 @@ class AmazonEchoApi:
868
926
  self,
869
927
  ) -> dict[str, AmazonDevice]:
870
928
  """Get Amazon devices data."""
871
- devices = {}
929
+ if not self._final_devices or (
930
+ datetime.now(UTC) - self._last_devices_refresh >= timedelta(days=1)
931
+ ):
932
+ # Request base device data
933
+ await self._get_base_devices()
934
+
935
+ if not self._endpoints or (
936
+ datetime.now(UTC) - self._last_endpoint_refresh >= timedelta(minutes=30)
937
+ ):
938
+ # Set device endpoint data
939
+ await self._set_device_endpoints_data()
940
+
941
+ await self._get_sensor_data()
942
+
943
+ return self._final_devices
944
+
945
+ async def _get_sensor_data(self) -> None:
946
+ devices_sensors = await self._get_sensors_states()
947
+ dnd_sensors = await self._get_dnd_status()
948
+ for device in self._final_devices.values():
949
+ # Update sensors
950
+ sensors = devices_sensors.get(device.serial_number, {})
951
+ if sensors:
952
+ device.sensors = sensors
953
+ else:
954
+ for device_sensor in device.sensors.values():
955
+ device_sensor.error = True
956
+ if device_dnd := dnd_sensors.get(device.serial_number):
957
+ device.sensors["dnd"] = device_dnd
958
+
959
+ async def _set_device_endpoints_data(self) -> None:
960
+ devices_endpoints = await self._get_devices_endpoint_data()
961
+ for serial_number in self._final_devices:
962
+ device_endpoint = devices_endpoints.get(serial_number, {})
963
+ endpoint_device = self._final_devices[serial_number]
964
+ endpoint_device.entity_id = (
965
+ device_endpoint["legacyIdentifiers"]["chrsIdentifier"]["entityId"]
966
+ if device_endpoint
967
+ else None
968
+ )
969
+ endpoint_device.endpoint_id = (
970
+ device_endpoint["endpointId"] if device_endpoint else None
971
+ )
972
+
973
+ async def _get_base_devices(self) -> None:
872
974
  _, raw_resp = await self._session_request(
873
975
  method=HTTPMethod.GET,
874
976
  url=f"https://alexa.amazon.{self._domain}{URI_DEVICES}",
@@ -885,7 +987,6 @@ class AmazonEchoApi:
885
987
  "Skipping device without serial number: %s", data["accountName"]
886
988
  )
887
989
  continue
888
- devices[dev_serial] = data
889
990
  if not self._account_owner_customer_id:
890
991
  self._account_owner_customer_id = (
891
992
  await self._get_account_owner_customer_id(data)
@@ -894,18 +995,13 @@ class AmazonEchoApi:
894
995
  if not self._account_owner_customer_id:
895
996
  raise CannotRetrieveData("Cannot find account owner customer ID")
896
997
 
897
- devices_endpoints, devices_sensors = await self._get_sensors_states(devices)
898
-
899
998
  final_devices_list: dict[str, AmazonDevice] = {}
900
- for device in devices.values():
999
+ for device in json_data["devices"]:
901
1000
  # Remove stale, orphaned and virtual devices
902
1001
  if not device or (device.get("deviceType") in DEVICE_TO_IGNORE):
903
1002
  continue
904
1003
 
905
1004
  serial_number: str = device["serialNumber"]
906
- # Add sensors
907
- sensors = devices_sensors.get(serial_number, {})
908
- device_endpoint = devices_endpoints.get(serial_number, {})
909
1005
 
910
1006
  final_devices_list[serial_number] = AmazonDevice(
911
1007
  account_name=device["accountName"],
@@ -919,13 +1015,9 @@ class AmazonEchoApi:
919
1015
  online=device["online"],
920
1016
  serial_number=serial_number,
921
1017
  software_version=device["softwareVersion"],
922
- entity_id=device_endpoint["legacyIdentifiers"]["chrsIdentifier"][
923
- "entityId"
924
- ]
925
- if device_endpoint
926
- else None,
927
- endpoint_id=device_endpoint["endpointId"] if device_endpoint else None,
928
- sensors=sensors,
1018
+ entity_id=None,
1019
+ endpoint_id=None,
1020
+ sensors={},
929
1021
  )
930
1022
 
931
1023
  self._list_for_clusters.update(
@@ -935,7 +1027,8 @@ class AmazonEchoApi:
935
1027
  }
936
1028
  )
937
1029
 
938
- return final_devices_list
1030
+ self._final_devices = final_devices_list
1031
+ self._last_devices_refresh = datetime.now(UTC)
939
1032
 
940
1033
  async def auth_check_status(self) -> bool:
941
1034
  """Check AUTH status."""
@@ -1240,3 +1333,24 @@ class AmazonEchoApi:
1240
1333
 
1241
1334
  _LOGGER.debug("Unexpected refresh data response")
1242
1335
  return False, {}
1336
+
1337
+ async def _get_dnd_status(self) -> dict[str, AmazonDeviceSensor]:
1338
+ dnd_status: dict[str, AmazonDeviceSensor] = {}
1339
+ _, raw_resp = await self._session_request(
1340
+ method=HTTPMethod.GET,
1341
+ url=f"https://alexa.amazon.{self._domain}{URI_DND}",
1342
+ )
1343
+
1344
+ dnd_data = await self._response_to_json(raw_resp)
1345
+ _LOGGER.debug("DND data: %s", dnd_data)
1346
+
1347
+ for dnd in dnd_data.get("doNotDisturbDeviceStatusList", {}):
1348
+ dnd_status[dnd.get("deviceSerialNumber")] = AmazonDeviceSensor(
1349
+ name="dnd",
1350
+ value=dnd.get("enabled"),
1351
+ error=False,
1352
+ error_type=None,
1353
+ error_msg=None,
1354
+ scale=None,
1355
+ )
1356
+ return dnd_status
aioamazondevices/const.py CHANGED
@@ -52,6 +52,7 @@ REFRESH_ACCESS_TOKEN = "access_token" # noqa: S105
52
52
  REFRESH_AUTH_COOKIES = "auth_cookies"
53
53
 
54
54
  URI_DEVICES = "/api/devices-v2/device"
55
+ URI_DND = "/api/dnd/device-status-list"
55
56
  URI_SIGNIN = "/ap/signin"
56
57
  URI_NEXUS_GRAPHQL = "/nexus/v1/graphql"
57
58
 
@@ -85,12 +86,6 @@ SENSORS: dict[str, dict[str, str | None]] = {
85
86
  "subkey": "value",
86
87
  "scale": None,
87
88
  },
88
- "speaker": {
89
- "name": "volume",
90
- "key": "value",
91
- "subkey": "volValue",
92
- "scale": None,
93
- },
94
89
  }
95
90
  DEVICE_TO_IGNORE: list[str] = [
96
91
  AMAZON_DEVICE_TYPE, # Alexa App for iOS
aioamazondevices/query.py CHANGED
@@ -1,8 +1,14 @@
1
1
  """GraphQL Queries."""
2
2
 
3
- QUERY_DEVICE_STATE = """
4
- query getDevicesState ($latencyTolerance: LatencyToleranceValue) {
5
- listEndpoints(listEndpointsInput: { includeHouseholdDevices: true }) {
3
+ QUERY_DEVICE_DATA = """
4
+ query getDevicesBaseData {
5
+ listEndpoints(
6
+ listEndpointsInput: {
7
+ displayCategory: "ALEXA_VOICE_ENABLED"
8
+ includeHouseholdDevices: true
9
+ }
10
+ )
11
+ {
6
12
  endpoints {
7
13
  endpointId: id
8
14
  friendlyNameObject { value { text } }
@@ -12,18 +18,6 @@ query getDevicesState ($latencyTolerance: LatencyToleranceValue) {
12
18
  softwareVersion { value { text } }
13
19
  creationTime
14
20
  enablement
15
- settings {
16
- doNotDisturb {
17
- id
18
- endpointId
19
- name
20
- toggleValue
21
- error {
22
- type
23
- message
24
- }
25
- }
26
- }
27
21
  displayCategories {
28
22
  all { value }
29
23
  primary { value }
@@ -41,48 +35,47 @@ query getDevicesState ($latencyTolerance: LatencyToleranceValue) {
41
35
  chrsIdentifier { entityId }
42
36
  }
43
37
  legacyAppliance { applianceId }
44
- associatedUnits { id }
45
- connections {
46
- type
47
- macAddress
48
- bleMeshDeviceUuid
49
- }
50
- features(latencyToleranceValue: $latencyTolerance) {
38
+ }
39
+ }
40
+ }
41
+ """
42
+
43
+ QUERY_SENSOR_STATE = """
44
+ query getEndpointState($endpointId: String!, $latencyTolerance: LatencyToleranceValue) {
45
+ endpoint(id: $endpointId) {
46
+ endpointId: id
47
+ features(latencyToleranceValue: $latencyTolerance) {
48
+ name
49
+ instance
50
+ properties {
51
51
  name
52
- instance
53
- properties {
52
+ type
53
+ accuracy
54
+ error { type message }
55
+ __typename
56
+ ... on Illuminance {
57
+ illuminanceValue { value }
58
+ timeOfSample
59
+ timeOfLastChange
60
+ }
61
+ ... on Reachability {
62
+ reachabilityStatusValue
63
+ timeOfSample
64
+ timeOfLastChange
65
+ }
66
+ ... on DetectionState {
67
+ detectionStateValue
68
+ timeOfSample
69
+ timeOfLastChange
70
+ }
71
+ ... on TemperatureSensor {
54
72
  name
55
- type
56
- accuracy
57
- error { message }
58
- __typename
59
- ... on Illuminance {
60
- illuminanceValue { value }
61
- timeOfSample
62
- timeOfLastChange
63
- }
64
- ... on Reachability {
65
- reachabilityStatusValue
66
- timeOfSample
67
- timeOfLastChange
68
- }
69
- ... on DetectionState {
70
- detectionStateValue
71
- timeOfSample
72
- timeOfLastChange
73
- }
74
- ... on Volume {
75
- value { volValue: value }
76
- }
77
- ... on TemperatureSensor {
78
- name
79
- value {
80
- value
81
- scale
82
- }
83
- timeOfSample
84
- timeOfLastChange
73
+ value {
74
+ value
75
+ scale
85
76
  }
77
+ timeOfSample
78
+ timeOfLastChange
86
79
  }
87
80
  }
88
81
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aioamazondevices
3
- Version: 6.2.9
3
+ Version: 6.4.0
4
4
  Summary: Python library to control Amazon devices
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -0,0 +1,12 @@
1
+ aioamazondevices/__init__.py,sha256=zz9ketTcgCPBPuHWcXvZG6yu5M4IxzEpRNRWvR4ETpc,276
2
+ aioamazondevices/api.py,sha256=YX-3khyvvvWdsq3XE2Q1P3AzRtkw-juWoBC_qdnGA3g,49661
3
+ aioamazondevices/const.py,sha256=A0aMbjPgIOAsSL20vjhAVkLBsi9QfkvL-1YAOEEa85I,11474
4
+ aioamazondevices/exceptions.py,sha256=gRYrxNAJnrV6uRuMx5e76VMvtNKyceXd09q84pDBBrI,638
5
+ aioamazondevices/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ aioamazondevices/query.py,sha256=SKn-fXFUnXnCvmKd6IvAGdkFL7sBzhYBEAZ0aZ2ez9E,1800
7
+ aioamazondevices/sounds.py,sha256=CXMDk-KoKVFxBdVAw3MeOClqgpzcVDxvQhFOJp7qX-Y,1896
8
+ aioamazondevices/utils.py,sha256=RzuKRhnq_8ymCoJMoQJ2vBYyuew06RSWpqQWmqdNczE,2019
9
+ aioamazondevices-6.4.0.dist-info/METADATA,sha256=xuedY3lpMT_rHFMdPFRh6IgxMiSB_requRjwulwbxRE,7656
10
+ aioamazondevices-6.4.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
11
+ aioamazondevices-6.4.0.dist-info/licenses/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
12
+ aioamazondevices-6.4.0.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- aioamazondevices/__init__.py,sha256=uARWO02mQ70rgxwWyOTxs9HC8FjeynIm_FBuhCenQBk,276
2
- aioamazondevices/api.py,sha256=B7KYropGmSwQl7sYzS7rTDDkiviIASsAszl1tsKDL70,45090
3
- aioamazondevices/const.py,sha256=pPjMhNABj3rN8uvHzqj41tDiGPx-C50QRcSckvzX9z8,11561
4
- aioamazondevices/exceptions.py,sha256=gRYrxNAJnrV6uRuMx5e76VMvtNKyceXd09q84pDBBrI,638
5
- aioamazondevices/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- aioamazondevices/query.py,sha256=qLCuNyVlSbvVQmckZUsmftsz8s04GIukdidsOo4BrD0,2084
7
- aioamazondevices/sounds.py,sha256=CXMDk-KoKVFxBdVAw3MeOClqgpzcVDxvQhFOJp7qX-Y,1896
8
- aioamazondevices/utils.py,sha256=RzuKRhnq_8ymCoJMoQJ2vBYyuew06RSWpqQWmqdNczE,2019
9
- aioamazondevices-6.2.9.dist-info/METADATA,sha256=0ULxMwg8faUXH8FU6_-2qvBd9Oc3LRm2HRVif5JJh7A,7656
10
- aioamazondevices-6.2.9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
11
- aioamazondevices-6.2.9.dist-info/licenses/LICENSE,sha256=sS48k5sp9bFV-NSHDfAJuTZZ_-AP9ZDqUzQ9sffGlsg,11346
12
- aioamazondevices-6.2.9.dist-info/RECORD,,