Skip to content

Commit 113a296

Browse files
committed
HA update to 2025.9 #14 and BUNCH HACS update #16
1 parent 41b9c13 commit 113a296

File tree

403 files changed

+24800
-3501
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

403 files changed

+24800
-3501
lines changed

.HA_VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2025.7.1
1+
2025.9.3

custom_components/alexa_media/__init__.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,9 @@ async def async_update_data() -> Optional[AlexaEntityData]:
433433
].values()
434434
auth_info = hass.data[DATA_ALEXAMEDIA]["accounts"][email].get("auth_info")
435435
new_devices = hass.data[DATA_ALEXAMEDIA]["accounts"][email]["new_devices"]
436-
should_get_network = False # get_network_details is deprecated
436+
should_get_network = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
437+
"should_get_network"
438+
]
437439
extended_entity_discovery = hass.data[DATA_ALEXAMEDIA]["accounts"][email][
438440
"options"
439441
].get(CONF_EXTENDED_ENTITY_DISCOVERY)
@@ -484,6 +486,9 @@ async def async_update_data() -> Optional[AlexaEntityData]:
484486
if entities_to_monitor:
485487
tasks.append(get_entity_data(login_obj, list(entities_to_monitor)))
486488

489+
if should_get_network:
490+
tasks.append(AlexaAPI.get_network_details(login_obj))
491+
487492
try:
488493
# Note: asyncio.TimeoutError and aiohttp.ClientError are already
489494
# handled by the data update coordinator.
@@ -496,7 +501,34 @@ async def async_update_data() -> Optional[AlexaEntityData]:
496501
*optional_task_results,
497502
) = await asyncio.gather(*tasks)
498503

499-
if entities_to_monitor:
504+
if should_get_network:
505+
_LOGGER.debug(
506+
"Alexa entities have been loaded. Prepared for discovery."
507+
)
508+
api_devices = optional_task_results.pop()
509+
if not api_devices:
510+
_LOGGER.warning(
511+
"%s: Alexa API returned an unexpected response while getting connected devices.",
512+
hide_email(email),
513+
)
514+
alexa_entities = parse_alexa_entities(api_devices)
515+
hass.data[DATA_ALEXAMEDIA]["accounts"][email]["devices"].update(
516+
alexa_entities
517+
)
518+
hass.data[DATA_ALEXAMEDIA]["accounts"][email][
519+
"should_get_network"
520+
] = False
521+
522+
# First run is a special case. Get the state of all entities(including disabled)
523+
# This ensures all entities have state during startup without needing to request coordinator refresh
524+
for type_of_entity, entities in alexa_entities.items():
525+
if type_of_entity == "guard" or extended_entity_discovery:
526+
for entity in entities:
527+
entities_to_monitor.add(entity.get("id"))
528+
entity_state = await get_entity_data(
529+
login_obj, list(entities_to_monitor)
530+
)
531+
elif entities_to_monitor:
500532
entity_state = optional_task_results.pop()
501533

502534
if new_devices:

custom_components/alexa_media/alexa_entity.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,20 +263,22 @@ def parse_alexa_entities(network_details: Optional[dict[str, Any]]) -> AlexaEnti
263263
air_quality_sensors = []
264264
contact_sensors = []
265265
switches = []
266-
location_details = (
267-
(network_details or {}).get("locationDetails", {}).get("locationDetails", {})
268-
)
269266

270-
appliances = {}
271-
for location in location_details.values():
272-
amazon_bridge_details = location["amazonBridgeDetails"]["amazonBridgeDetails"]
273-
for bridge in amazon_bridge_details.values():
274-
appliance_details = bridge["applianceDetails"]["applianceDetails"]
275-
for appliance in appliance_details.values():
276-
appliances[appliance["applianceId"]] = appliance
267+
if not network_details:
268+
return {
269+
"light": lights,
270+
"guard": guards,
271+
"temperature": temperature_sensors,
272+
"air_quality": air_quality_sensors,
273+
"binary_sensor": contact_sensors,
274+
"smart_switch": switches,
275+
}
276+
network_dict = {}
277+
for appliance in network_details:
278+
network_dict[appliance["applianceId"]] = appliance
277279

278-
for appliance in appliances.values():
279-
device_bridge = get_device_bridge(appliance, appliances)
280+
for appliance in network_details:
281+
device_bridge = get_device_bridge(appliance, network_dict)
280282
if is_known_ha_bridge(device_bridge):
281283
_LOGGER.debug("Found Home Assistant bridge, skipping %s", appliance)
282284
continue
@@ -518,7 +520,7 @@ def is_cap_state_still_acceptable(
518520
if formatted_time_of_sample:
519521
try:
520522
time_of_sample = datetime.strptime(
521-
formatted_time_of_sample, "%Y-%m-%dT%H:%M:%S.%f%z"
523+
formatted_time_of_sample, "%Y-%m-%dT%H:%M:%S%z"
522524
)
523525
return time_of_sample >= since
524526
except ValueError:

custom_components/alexa_media/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
PERCENTAGE,
1616
)
1717

18-
__version__ = "5.7.3"
18+
__version__ = "5.7.5"
1919
PROJECT_URL = "https://github.com/alandtse/alexa_media_player/"
2020
ISSUE_URL = f"{PROJECT_URL}issues"
2121
NOTIFY_URL = f"{PROJECT_URL}wiki/Configuration%3A-Notification-Component#use-the-notifyalexa_media-service"
Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
1-
"""Alexa Media Exceptions"""
2-
3-
4-
class EmptyDataException(Exception):
5-
"""Empty data exception"""
6-
7-
8-
class ForbiddenException(Exception):
9-
"""Forbidden exception"""
10-
11-
12-
class LoginForbiddenException(Exception):
13-
"""Login forbidden exception"""
14-
15-
16-
class LoginInvalidException(Exception):
17-
"""Invalid login exception"""
18-
19-
def __init__(self, attempts_remaining):
20-
self.attempts_remaining = attempts_remaining
21-
super().__init__(
22-
f"Invalid login credentials. {attempts_remaining} attempts remaining."
23-
)
24-
25-
26-
class TimeoutException(Exception):
27-
"""Timeout exception"""
28-
29-
def __init__(self, message=""):
30-
super().__init__(f"Timeour exception: {message}")
31-
32-
33-
class UnexpectedApiException(Exception):
34-
"""Unexpected API exception"""
1+
"""Alexa Media Exceptions"""
2+
3+
4+
class EmptyDataException(Exception):
5+
"""Empty data exception"""
6+
7+
8+
class ForbiddenException(Exception):
9+
"""Forbidden exception"""
10+
11+
12+
class LoginForbiddenException(Exception):
13+
"""Login forbidden exception"""
14+
15+
16+
class LoginInvalidException(Exception):
17+
"""Invalid login exception"""
18+
19+
def __init__(self, attempts_remaining):
20+
self.attempts_remaining = attempts_remaining
21+
super().__init__(
22+
f"Invalid login credentials. {attempts_remaining} attempts remaining."
23+
)
24+
25+
26+
class TimeoutException(Exception):
27+
"""Timeout exception"""
28+
29+
def __init__(self, message=""):
30+
super().__init__(f"Timeout exception: {message}")
31+
32+
33+
class UnexpectedApiException(Exception):
34+
"""Unexpected API exception"""

custom_components/alexa_media/light.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ def alexa_color_name_to_rgb(color_name: str) -> tuple[int, int, int]:
490490

491491

492492
def rgb_to_alexa_color(
493-
rgb: tuple[int, int, int]
493+
rgb: tuple[int, int, int],
494494
) -> tuple[Optional[tuple[float, float]], Optional[str]]:
495495
"""Convert a given RGB value into the closest Alexa color."""
496496
(name, alexa_rgb) = min(
@@ -502,7 +502,7 @@ def rgb_to_alexa_color(
502502

503503

504504
def hs_to_alexa_color(
505-
hs_color: Optional[tuple[float, float]]
505+
hs_color: Optional[tuple[float, float]],
506506
) -> tuple[Optional[tuple[float, float]], Optional[str]]:
507507
"""Convert a given hue/saturation value into the closest Alexa color."""
508508
if hs_color is None:
@@ -512,7 +512,7 @@ def hs_to_alexa_color(
512512

513513

514514
def hsb_to_alexa_color(
515-
hsb: Optional[tuple[float, float, float]]
515+
hsb: Optional[tuple[float, float, float]],
516516
) -> tuple[Optional[tuple[float, float]], Optional[str]]:
517517
"""Convert a given hue/saturation/brightness value into the closest Alexa color."""
518518
if hsb is None:

custom_components/alexa_media/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
"iot_class": "cloud_polling",
99
"issue_tracker": "https://github.com/alandtse/alexa_media_player/issues",
1010
"loggers": ["alexapy", "authcaptureproxy"],
11-
"requirements": ["alexapy==1.29.5", "packaging>=20.3", "wrapt>=1.14.0"],
12-
"version": "5.7.3"
11+
"requirements": ["alexapy==1.29.8", "packaging>=20.3", "wrapt>=1.14.0"],
12+
"version": "5.7.7"
1313
}

custom_components/alexa_media/media_player.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ def state(self):
10211021
return MediaPlayerState.PAUSED
10221022
if self._media_player_state == "IDLE":
10231023
return MediaPlayerState.IDLE
1024-
return MediaPlayerState.STANDBY
1024+
return MediaPlayerState.IDLE
10251025

10261026
def update(self):
10271027
"""Get the latest details on a media player synchronously."""
@@ -1143,7 +1143,7 @@ def media_content_type(self):
11431143
"""Return the content type of current playing media."""
11441144
if self.state in [MediaPlayerState.PLAYING, MediaPlayerState.PAUSED]:
11451145
return MediaType.MUSIC
1146-
return MediaPlayerState.STANDBY
1146+
return MediaPlayerState.IDLE
11471147

11481148
@property
11491149
def media_artist(self):

0 commit comments

Comments
 (0)