Skip to content

Commit

Permalink
2024.9.1 (#125420)
Browse files Browse the repository at this point in the history
  • Loading branch information
balloob authored Sep 6, 2024
2 parents 36ec1b3 + ed2d321 commit 4445605
Show file tree
Hide file tree
Showing 53 changed files with 541 additions and 236 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/airtouch5/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
_LOGGER.debug("Argument `temperature` is missing in set_temperature")
return

await self._control(temp=temp)
await self._control(setpoint=SetpointControl.CHANGE_SETPOINT, temp=temp)


class Airtouch5Zone(Airtouch5ClimateEntity):
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/apple_tv/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"documentation": "https://www.home-assistant.io/integrations/apple_tv",
"iot_class": "local_push",
"loggers": ["pyatv", "srptools"],
"requirements": ["pyatv==0.15.0"],
"requirements": ["pyatv==0.15.1"],
"zeroconf": [
"_mediaremotetv._tcp.local.",
"_companion-link._tcp.local.",
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/apsystems/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ def __init__(self, hass: HomeAssistant, api: APsystemsEZ1M) -> None:

async def _async_setup(self) -> None:
try:
max_power = (await self.api.get_device_info()).maxPower
device_info = await self.api.get_device_info()
except (ConnectionError, TimeoutError):
raise UpdateFailed from None
self.api.max_power = max_power
self.api.max_power = device_info.maxPower
self.api.min_power = device_info.minPower

async def _async_update_data(self) -> ApSystemsSensorData:
output_data = await self.api.get_output_data()
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/apsystems/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ async def async_setup_entry(
class ApSystemsMaxOutputNumber(ApSystemsEntity, NumberEntity):
"""Base sensor to be used with description."""

_attr_native_min_value = 30
_attr_native_step = 1
_attr_device_class = NumberDeviceClass.POWER
_attr_mode = NumberMode.BOX
Expand All @@ -42,6 +41,7 @@ def __init__(
self._api = data.coordinator.api
self._attr_unique_id = f"{data.device_id}_output_limit"
self._attr_native_max_value = data.coordinator.api.max_power
self._attr_native_min_value = data.coordinator.api.min_power

async def async_update(self) -> None:
"""Set the state with the value fetched from the inverter."""
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/aquacell/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async def async_step_user(
refresh_token = await api.authenticate(
user_input[CONF_EMAIL], user_input[CONF_PASSWORD]
)
except ApiException:
except (ApiException, TimeoutError):
errors["base"] = "cannot_connect"
except AuthenticationFailed:
errors["base"] = "invalid_auth"
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/aquacell/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ async def _async_update_data(self) -> dict[str, Softener]:
so entities can quickly look up their data.
"""

async with asyncio.timeout(10):
async with asyncio.timeout(30):
# Check if the refresh token is expired
expiry_time = (
self.refresh_token_creation_time
Expand All @@ -72,7 +72,7 @@ async def _async_update_data(self) -> dict[str, Softener]:
softeners = await self.aquacell_api.get_all_softeners()
except AuthenticationFailed as err:
raise ConfigEntryError from err
except AquacellApiException as err:
except (AquacellApiException, TimeoutError) as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err

return {softener.dsn: softener for softener in softeners}
Expand Down
56 changes: 36 additions & 20 deletions homeassistant/components/bthome/device_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import voluptuous as vol

from homeassistant.components.device_automation import DEVICE_TRIGGER_BASE_SCHEMA
from homeassistant.components.device_automation.exceptions import (
InvalidDeviceAutomationConfig,
)
from homeassistant.components.homeassistant.triggers import event as event_trigger
from homeassistant.const import (
CONF_DEVICE_ID,
Expand Down Expand Up @@ -43,34 +46,47 @@
EVENT_CLASS_DIMMER: {"rotate_left", "rotate_right"},
}

SCHEMA_BY_EVENT_CLASS = {
EVENT_CLASS_BUTTON: DEVICE_TRIGGER_BASE_SCHEMA.extend(
{
vol.Required(CONF_TYPE): vol.In([EVENT_CLASS_BUTTON]),
vol.Required(CONF_SUBTYPE): vol.In(
TRIGGERS_BY_EVENT_CLASS[EVENT_CLASS_BUTTON]
),
}
),
EVENT_CLASS_DIMMER: DEVICE_TRIGGER_BASE_SCHEMA.extend(
{
vol.Required(CONF_TYPE): vol.In([EVENT_CLASS_DIMMER]),
vol.Required(CONF_SUBTYPE): vol.In(
TRIGGERS_BY_EVENT_CLASS[EVENT_CLASS_DIMMER]
),
}
),
}
TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
{vol.Required(CONF_TYPE): str, vol.Required(CONF_SUBTYPE): str}
)


async def async_validate_trigger_config(
hass: HomeAssistant, config: ConfigType
) -> ConfigType:
"""Validate trigger config."""
return SCHEMA_BY_EVENT_CLASS.get(config[CONF_TYPE], DEVICE_TRIGGER_BASE_SCHEMA)( # type: ignore[no-any-return]
config
config = TRIGGER_SCHEMA(config)
event_class = config[CONF_TYPE]
event_type = config[CONF_SUBTYPE]

device_registry = dr.async_get(hass)
device = device_registry.async_get(config[CONF_DEVICE_ID])
assert device is not None
config_entries = [
hass.config_entries.async_get_entry(entry_id)
for entry_id in device.config_entries
]
bthome_config_entry = next(
iter(entry for entry in config_entries if entry and entry.domain == DOMAIN)
)
event_classes: list[str] = bthome_config_entry.data.get(
CONF_DISCOVERED_EVENT_CLASSES, []
)

if event_class not in event_classes:
raise InvalidDeviceAutomationConfig(
f"BTHome trigger {event_class} is not valid for device "
f"{device} ({config[CONF_DEVICE_ID]})"
)

if event_type not in TRIGGERS_BY_EVENT_CLASS.get(event_class.split("_")[0], ()):
raise InvalidDeviceAutomationConfig(
f"BTHome trigger {event_type} is not valid for device "
f"{device} ({config[CONF_DEVICE_ID]})"
)

return config


async def async_get_triggers(
hass: HomeAssistant, device_id: str
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/envisalink/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __init__(
self._partition_number = partition_number
self._panic_type = panic_type
self._alarm_control_panel_option_default_code = code
self._attr_code_format = CodeFormat.NUMBER
self._attr_code_format = CodeFormat.NUMBER if not code else None

_LOGGER.debug("Setting up alarm: %s", alarm_name)
super().__init__(alarm_name, info, controller)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20240904.0"]
"requirements": ["home-assistant-frontend==20240906.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/fyta/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(self, hass: HomeAssistant, fyta: FytaConnector) -> None:
hass,
_LOGGER,
name="FYTA Coordinator",
update_interval=timedelta(seconds=60),
update_interval=timedelta(minutes=4),
)
self.fyta = fyta

Expand Down
6 changes: 5 additions & 1 deletion homeassistant/components/hue/v2/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,11 @@ async def async_turn_on(self, **kwargs: Any) -> None:
flash = kwargs.get(ATTR_FLASH)
effect = effect_str = kwargs.get(ATTR_EFFECT)
if effect_str in (EFFECT_NONE, EFFECT_NONE.lower()):
effect = EffectStatus.NO_EFFECT
# ignore effect if set to "None" and we have no effect active
# the special effect "None" is only used to stop an active effect
# but sending it while no effect is active can actually result in issues
# https://github.com/home-assistant/core/issues/122165
effect = None if self.effect == EFFECT_NONE else EffectStatus.NO_EFFECT
elif effect_str is not None:
# work out if we got a regular effect or timed effect
effect = EffectStatus(effect_str)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/lcn/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"documentation": "https://www.home-assistant.io/integrations/lcn",
"iot_class": "local_push",
"loggers": ["pypck"],
"requirements": ["pypck==0.7.21", "lcn-frontend==0.1.6"]
"requirements": ["pypck==0.7.22", "lcn-frontend==0.1.6"]
}
16 changes: 12 additions & 4 deletions homeassistant/components/linkplay/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
MediaType,
RepeatMode,
)
from homeassistant.components.media_player.browse_media import (
async_process_play_media_url,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
Expand Down Expand Up @@ -59,6 +62,7 @@
PlayingMode.FM: "FM Radio",
PlayingMode.RCA: "RCA",
PlayingMode.UDISK: "USB",
PlayingMode.FOLLOWER: "Follower",
}

SOURCE_MAP_INV: dict[str, PlayingMode] = {v: k for k, v in SOURCE_MAP.items()}
Expand Down Expand Up @@ -233,10 +237,14 @@ async def async_play_media(
self, media_type: MediaType | str, media_id: str, **kwargs: Any
) -> None:
"""Play a piece of media."""
media = await media_source.async_resolve_media(
self.hass, media_id, self.entity_id
)
await self._bridge.player.play(media.url)
if media_source.is_media_source_id(media_id):
play_item = await media_source.async_resolve_media(
self.hass, media_id, self.entity_id
)
media_id = play_item.url

url = async_process_play_media_url(self.hass, media_id)
await self._bridge.player.play(url)

def _update_properties(self) -> None:
"""Update the properties of the media player."""
Expand Down
26 changes: 13 additions & 13 deletions homeassistant/components/lyric/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,8 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
await self._update_thermostat(
self.location,
device,
coolSetpoint=target_temp_high,
heatSetpoint=target_temp_low,
cool_setpoint=target_temp_high,
heat_setpoint=target_temp_low,
mode=mode,
)
except LYRIC_EXCEPTIONS as exception:
Expand All @@ -371,11 +371,11 @@ async def async_set_temperature(self, **kwargs: Any) -> None:
try:
if self.hvac_mode == HVACMode.COOL:
await self._update_thermostat(
self.location, device, coolSetpoint=temp
self.location, device, cool_setpoint=temp
)
else:
await self._update_thermostat(
self.location, device, heatSetpoint=temp
self.location, device, heat_setpoint=temp
)
except LYRIC_EXCEPTIONS as exception:
_LOGGER.error(exception)
Expand Down Expand Up @@ -410,7 +410,7 @@ async def _async_set_hvac_mode_tcc(self, hvac_mode: HVACMode) -> None:
self.location,
self.device,
mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT],
autoChangeoverActive=False,
auto_changeover_active=False,
)
# Sleep 3 seconds before proceeding
await asyncio.sleep(3)
Expand All @@ -422,29 +422,29 @@ async def _async_set_hvac_mode_tcc(self, hvac_mode: HVACMode) -> None:
self.location,
self.device,
mode=HVAC_MODES[LYRIC_HVAC_MODE_HEAT],
autoChangeoverActive=True,
auto_changeover_active=True,
)
else:
_LOGGER.debug(
"HVAC mode passed to lyric: %s",
HVAC_MODES[self.device.changeable_values.mode],
)
await self._update_thermostat(
self.location, self.device, autoChangeoverActive=True
self.location, self.device, auto_changeover_active=True
)
else:
_LOGGER.debug("HVAC mode passed to lyric: %s", LYRIC_HVAC_MODES[hvac_mode])
await self._update_thermostat(
self.location,
self.device,
mode=LYRIC_HVAC_MODES[hvac_mode],
autoChangeoverActive=False,
auto_changeover_active=False,
)

async def _async_set_hvac_mode_lcc(self, hvac_mode: HVACMode) -> None:
"""Set hvac mode for LCC devices (e.g., T5,6)."""
_LOGGER.debug("HVAC mode passed to lyric: %s", LYRIC_HVAC_MODES[hvac_mode])
# Set autoChangeoverActive to True if the mode being passed is Auto
# Set auto_changeover_active to True if the mode being passed is Auto
# otherwise leave unchanged.
if (
LYRIC_HVAC_MODES[hvac_mode] == LYRIC_HVAC_MODE_HEAT_COOL
Expand All @@ -458,15 +458,15 @@ async def _async_set_hvac_mode_lcc(self, hvac_mode: HVACMode) -> None:
self.location,
self.device,
mode=LYRIC_HVAC_MODES[hvac_mode],
autoChangeoverActive=auto_changeover,
auto_changeover_active=auto_changeover,
)

async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set preset (PermanentHold, HoldUntil, NoHold, VacationHold) mode."""
_LOGGER.debug("Set preset mode: %s", preset_mode)
try:
await self._update_thermostat(
self.location, self.device, thermostatSetpointStatus=preset_mode
self.location, self.device, thermostat_setpoint_status=preset_mode
)
except LYRIC_EXCEPTIONS as exception:
_LOGGER.error(exception)
Expand All @@ -479,8 +479,8 @@ async def async_set_hold_time(self, time_period: str) -> None:
await self._update_thermostat(
self.location,
self.device,
thermostatSetpointStatus=PRESET_HOLD_UNTIL,
nextPeriodTime=time_period,
thermostat_setpoint_status=PRESET_HOLD_UNTIL,
next_period_time=time_period,
)
except LYRIC_EXCEPTIONS as exception:
_LOGGER.error(exception)
Expand Down
10 changes: 4 additions & 6 deletions homeassistant/components/russound_rio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import asyncio
import logging

from aiorussound import Russound
from aiorussound import RussoundClient, RussoundTcpConnectionHandler

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
Expand All @@ -16,15 +16,15 @@

_LOGGER = logging.getLogger(__name__)

type RussoundConfigEntry = ConfigEntry[Russound]
type RussoundConfigEntry = ConfigEntry[RussoundClient]


async def async_setup_entry(hass: HomeAssistant, entry: RussoundConfigEntry) -> bool:
"""Set up a config entry."""

host = entry.data[CONF_HOST]
port = entry.data[CONF_PORT]
russ = Russound(hass.loop, host, port)
russ = RussoundClient(RussoundTcpConnectionHandler(hass.loop, host, port))

@callback
def is_connected_updated(connected: bool) -> None:
Expand All @@ -37,14 +37,12 @@ def is_connected_updated(connected: bool) -> None:
port,
)

russ.add_connection_callback(is_connected_updated)

russ.connection_handler.add_connection_callback(is_connected_updated)
try:
async with asyncio.timeout(CONNECT_TIMEOUT):
await russ.connect()
except RUSSOUND_RIO_EXCEPTIONS as err:
raise ConfigEntryNotReady(f"Error while connecting to {host}:{port}") from err

entry.runtime_data = russ

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
Expand Down
Loading

0 comments on commit 4445605

Please sign in to comment.