Compare commits

...

93 Commits

Author SHA1 Message Date
Franck Nijhof
777b3128bb 2025.7.4 (#149526) 2025-07-28 10:15:08 +02:00
Franck Nijhof
d384bee576 Bump version to 2025.7.4 2025-07-27 17:35:19 +00:00
Manu
f0cb5d5480 Bump habiticalib to v0.4.1 (#149523) 2025-07-27 17:35:01 +00:00
jb101010-2
725799c73e Bump pysuezV2 to 2.0.7 (#149436) 2025-07-27 17:34:59 +00:00
Simone Chemelli
dc6d2e3e84 Bump aioamazondevices to 3.5.1 (#149385) 2025-07-27 17:34:09 +00:00
Alex Hermann
4a7d06a68a Update slixmpp to 1.10.0 (#149374) 2025-07-27 17:29:37 +00:00
Brett Adams
cd800da357 Update Tesla OAuth Server in Tesla Fleet (#149280) 2025-07-27 17:29:35 +00:00
Antoine Reversat
4c8ab8eb64 Add fan off mode to the supported fan modes to fujitsu_fglair (#149277) 2025-07-27 17:29:33 +00:00
Martin Hjelmare
60f4d29d60 Add Z-Wave USB migration confirm step (#149243) 2025-07-27 17:29:31 +00:00
Avi Miller
68b7d09476 Fix brightness_step and brightness_step_pct via lifx.set_state (#149217)
Signed-off-by: Avi Miller <me@dje.li>
2025-07-27 17:29:29 +00:00
jvmahon
c3eb6dea11 Fix Matter light get brightness (#149186) 2025-07-27 17:29:28 +00:00
David Knowles
f428ffde87 Bump pyschlage to 2025.7.2 (#149148) 2025-07-27 17:29:26 +00:00
hanwg
fa207860a0 Fix multiple webhook secrets for Telegram bot (#149103) 2025-07-27 17:29:24 +00:00
Allen Porter
959c3a8a99 Fix a bug in rainbird device migration that results in additional devices (#149078) 2025-07-27 17:29:23 +00:00
Marc Hörsken
254ccca4e5 Fix warning about failure to get action during setup phase (#148923) 2025-07-27 17:29:21 +00:00
AlCalzone
5b08724d81 Keep entities of dead Z-Wave devices available (#148611) 2025-07-27 17:29:20 +00:00
Bram Kragten
456f992b7e 2025.7.3 (#149024) 2025-07-22 10:30:09 +02:00
Franck Nijhof
0675e34c62 Bump version to 2025.7.3 2025-07-18 17:05:52 +00:00
Simone Chemelli
190c98f5a8 Bump aioamazondevices to 3.5.0 (#149011) 2025-07-18 17:04:01 +00:00
Jan Bouwhuis
c6bb26be89 Ignore MQTT sensor unit of measurement if it is an empty string (#149006) 2025-07-18 17:02:02 +00:00
J. Nick Koston
d57c5ffa8f Bump PySwitchbot to 0.68.2 (#148996) 2025-07-18 17:02:01 +00:00
Bram Kragten
68889e1790 Update frontend to 20250702.3 (#148994) 2025-07-18 17:02:00 +00:00
Joost Lekkerkerker
8fdc50a29f Pass Syncthru entry to coordinator (#148974) 2025-07-18 17:01:58 +00:00
Steven Looman
5656b4c20d Bump async-upnp-client to 0.45.0 (#148961) 2025-07-18 17:01:57 +00:00
Maciej Bieniek
b6edcc9422 Bump gios to version 6.1.2 (#148884) 2025-07-18 17:01:56 +00:00
Maciej Bieniek
7a3eb53453 Bump gios to version 6.1.1 (#148414) 2025-07-18 17:01:54 +00:00
Arie Catsman
11a2c73e8a Bump pyenphase to 2.2.2 (#148870) 2025-07-18 17:00:32 +00:00
Brett Adams
1644484c92 Fix button platform parent class in Teslemetry (#148863) 2025-07-18 17:00:30 +00:00
Pete Sage
8e0a89dc2f Add guard to prevent exception in Sonos Favorites (#148854) 2025-07-18 17:00:29 +00:00
Robert Resch
9e4b8df344 Use ffmpeg for generic cameras in go2rtc (#148818) 2025-07-18 17:00:28 +00:00
Brett Adams
69fdc1d269 Bump Tesla Fleet API to 1.2.2 (#148776) 2025-07-18 17:00:26 +00:00
Joost Lekkerkerker
56e0aa103d Bump pySmartThings to 3.2.8 (#148761) 2025-07-18 17:00:25 +00:00
Maciej Bieniek
caf0492009 Fix Shelly n_current sensor removal condition (#148740) 2025-07-18 17:00:24 +00:00
hahn-th
c6d0aad3d3 Handle connection issues after websocket reconnected in homematicip_cloud (#147731) 2025-07-18 17:00:22 +00:00
Franck Nijhof
1f59b735c6 2025.7.2 (#148725) 2025-07-14 13:12:29 +02:00
Franck Nijhof
87af9fc8ba Bump version to 2025.7.2 2025-07-14 10:30:35 +00:00
Simone Chemelli
691a0ca065 Bump aioamazondevices to 3.2.10 (#148709) 2025-07-14 10:27:45 +00:00
Shay Levy
80384b89a5 Bump aioshelly to 13.7.2 (#148706) 2025-07-14 10:25:24 +00:00
Jan Bouwhuis
f7672985ed Fix hide empty sections in mqtt subentry flows (#148692) 2025-07-14 10:25:23 +00:00
Christopher Fenner
d4374dbcc7 Bump PyViCare to 2.50.0 (#148679) 2025-07-14 10:25:22 +00:00
Brett Adams
c4ddcd64c8 Fix Charge Cable binary sensor in Teslemetry (#148675) 2025-07-14 10:25:21 +00:00
0xEF
c802430066 Bump nyt_games to 0.5.0 (#148654) 2025-07-14 10:25:20 +00:00
falconindy
649fbfc729 snoo: use correct value for right safety clip binary sensor (#148647) 2025-07-14 10:25:18 +00:00
Jan Bouwhuis
80c52ad8ea Fix - only enable AlexaModeController if at least one mode is offered (#148614) 2025-07-14 10:25:17 +00:00
Lưu Quang Vũ
150d4716fa Fix Google Cloud 504 Deadline Exceeded (#148589) 2025-07-14 10:25:16 +00:00
Bram Kragten
dc2736580f Update frontend to 20250702.2 (#148573) 2025-07-14 10:25:15 +00:00
J. Nick Koston
f1272ef513 Bump aiohttp to 3.12.14 (#148565) 2025-07-14 10:25:14 +00:00
Åke Strandberg
3c2fa023b4 Remove vg argument from miele auth flow (#148541) 2025-07-14 10:25:12 +00:00
Kristof Mariën
5cf5be8c9c Fix for Renson set Breeze fan speed (#148537) 2025-07-14 10:25:11 +00:00
Jan-Philipp Benecke
63b21fda1a Ensure response is fully read to prevent premature connection closure in rest command (#148532) 2025-07-14 10:25:10 +00:00
J. Diego Rodríguez Royo
d87379d083 Use the link to the issue instead of creating new issues at Home Connect (#148523) 2025-07-14 10:25:09 +00:00
J. Diego Rodríguez Royo
0990cef917 Add Home Connect resume command button when an appliance is paused (#148512) 2025-07-14 10:25:08 +00:00
Michael
962ad99c20 Add workaround for sub units without main device in AVM Fritz!SmartHome (#148507) 2025-07-14 10:25:07 +00:00
Michael
9c9836defd Bump aioimmich to 0.10.2 (#148503) 2025-07-14 10:25:06 +00:00
Jan Bouwhuis
e951fc401c Fix entity_id should be based on object_id the first time an entity is added (#148484) 2025-07-14 10:25:05 +00:00
Robert Resch
00e2a177a5 Revert "Deprecate hddtemp" (#148482) 2025-07-14 10:25:04 +00:00
Joakim Sørensen
b6d316c8f2 Bump hass-nabucasa from 0.105.0 to 0.106.0 (#148473) 2025-07-14 10:25:02 +00:00
Raphael Hehl
b8425de0d0 Bump uiprotect to version 7.14.2 (#148453) 2025-07-14 10:25:01 +00:00
Joost Lekkerkerker
d51a44acbc Bump pySmartThings to 3.2.7 (#148394) 2025-07-14 10:25:00 +00:00
Josef Zweck
435465e569 Bump pylamarzocco to 2.0.11 (#148386) 2025-07-14 10:24:59 +00:00
Josef Zweck
3b047859f9 Create own clientsession for lamarzocco (#148385) 2025-07-14 10:24:58 +00:00
Simone Chemelli
91cdf1a367 Bump aioamazondevices to 3.2.8 (#148365)
Co-authored-by: Joakim Plate <elupus@ecce.se>
2025-07-14 10:24:57 +00:00
Joakim Plate
2377b136f3 Handle binary coils with non default mappings in nibe heatpump (#148354) 2025-07-14 10:24:56 +00:00
Retha Runolfsson
186c4e7038 Bump pyswitchbot to 0.68.1 (#148335) 2025-07-14 10:24:55 +00:00
Samuel Xiao
d303a7d17e Fix Switchbot cloud plug mini current unit Issue (#148314) 2025-07-14 10:24:54 +00:00
jvits227
14f059c766 Add lamp states to smartthings selector (#148302)
Co-authored-by: Joostlek <joostlek@outlook.com>
2025-07-14 10:23:55 +00:00
Arie Catsman
4a10370932 Bump pyenphase to 2.2.1 (#148292) 2025-07-14 10:13:43 +00:00
J. Nick Koston
672ffa5984 Restore httpx compatibility for non-primitive REST query parameters (#148286) 2025-07-14 10:13:42 +00:00
Maciej Bieniek
3d3f2527cb Bump gios to version 6.1.0 (#148274) 2025-07-14 10:13:41 +00:00
Shay Levy
5c3b279f95 Bump aiowebostv to 0.7.4 (#148273) 2025-07-14 10:13:40 +00:00
starkillerOG
59bcf1167a bump motionblinds to 0.6.29 (#148265) 2025-07-14 10:13:39 +00:00
Mark Adkins
b4d789f8e2 Bump sharkiq to 1.1.1 (#148244) 2025-07-14 10:12:00 +00:00
Josef Zweck
f4ca56052b Bump pylamarzocco to 2.0.10 (#148233) 2025-07-14 10:11:59 +00:00
J. Nick Koston
74f9549431 Fix UTF-8 encoding for REST basic authentication (#148225) 2025-07-14 10:11:58 +00:00
J. Nick Koston
9650727515 Fix REST sensor charset handling to respect Content-Type header (#148223) 2025-07-14 10:11:57 +00:00
TimL
c965da6559 Bump pysmlight to v0.2.7 (#148101)
Co-authored-by: Franck Nijhof <git@frenck.dev>
2025-07-14 10:09:19 +00:00
Sören Beye
9077965214 Squeezebox: Fix tracks not having thumbnails (#147187) 2025-07-14 10:09:18 +00:00
Sören Beye
2b7992e849 Squeezebox: Fix track selection in media browser (#147185) 2025-07-14 10:09:16 +00:00
Franck Nijhof
5d6b02f470 2025.7.1 (#148171) 2025-07-04 22:00:18 +02:00
Franck Nijhof
a274961593 Bump version to 2025.7.1 2025-07-04 19:22:41 +00:00
Michael Freeman
4e163c4591 Bump venstarcolortouch to 0.21 (#148152) 2025-07-04 19:21:33 +00:00
Marc Mueller
3ffec2a655 [ci] Fix typing issue with aiohttp and aiosignal (#148141) 2025-07-04 19:21:31 +00:00
Bram Kragten
c646658643 Update frontend to 20250702.1 (#148131) 2025-07-04 19:21:30 +00:00
Simone Chemelli
342b4c3442 Bump aioamazondevices to 3.2.3 (#148082) 2025-07-04 19:21:28 +00:00
Arie Catsman
eb58c10e5e Cancel enphase mac verification on unload. (#148072) 2025-07-04 19:21:27 +00:00
Arie Catsman
f42e7d982f Bump pyenphase to 2.2.0 (#148070) 2025-07-04 19:21:25 +00:00
hanwg
898ef43750 Fix Telegram bots using plain text parser failing to load on restart (#148050) 2025-07-04 19:21:24 +00:00
Joakim Sørensen
f806e6ba49 Bump hass-nabucasa from 0.104.0 to 0.105.0 (#148040) 2025-07-04 19:21:23 +00:00
Marcel van der Veldt
c23bfb1b39 Fix state being incorrectly reported in some situations on Music Assistant players (#147997) 2025-07-04 19:21:22 +00:00
Robert Svensson
a2ffe32b02 Bump aiounifi to v84 (#147987) 2025-07-04 19:21:21 +00:00
puddly
0f32b6331d Bump ZHA to 0.0.62 (#147966) 2025-07-04 19:21:19 +00:00
epenet
9a4959560e Fix missing port in samsungtv (#147962)
Co-authored-by: Abílio Costa <abmantis@users.noreply.github.com>
2025-07-04 19:21:18 +00:00
Thomas55555
41ab7b346c Set timeout for remote calendar (#147024) 2025-07-04 19:21:17 +00:00
152 changed files with 2225 additions and 595 deletions

View File

@@ -37,7 +37,7 @@ on:
type: boolean
env:
CACHE_VERSION: 3
CACHE_VERSION: 4
UV_CACHE_VERSION: 1
MYPY_CACHE_VERSION: 1
HA_SHORT_VERSION: "2025.7"

View File

@@ -505,8 +505,13 @@ class ClimateCapabilities(AlexaEntity):
):
yield AlexaThermostatController(self.hass, self.entity)
yield AlexaTemperatureSensor(self.hass, self.entity)
if self.entity.domain == water_heater.DOMAIN and (
supported_features & water_heater.WaterHeaterEntityFeature.OPERATION_MODE
if (
self.entity.domain == water_heater.DOMAIN
and (
supported_features
& water_heater.WaterHeaterEntityFeature.OPERATION_MODE
)
and self.entity.attributes.get(water_heater.ATTR_OPERATION_LIST)
):
yield AlexaModeController(
self.entity,
@@ -634,7 +639,9 @@ class FanCapabilities(AlexaEntity):
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}"
)
force_range_controller = False
if supported & fan.FanEntityFeature.PRESET_MODE:
if supported & fan.FanEntityFeature.PRESET_MODE and self.entity.attributes.get(
fan.ATTR_PRESET_MODES
):
yield AlexaModeController(
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_PRESET_MODE}"
)
@@ -672,7 +679,11 @@ class RemoteCapabilities(AlexaEntity):
yield AlexaPowerController(self.entity)
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
activities = self.entity.attributes.get(remote.ATTR_ACTIVITY_LIST) or []
if activities and supported & remote.RemoteEntityFeature.ACTIVITY:
if (
activities
and (supported & remote.RemoteEntityFeature.ACTIVITY)
and self.entity.attributes.get(remote.ATTR_ACTIVITY_LIST)
):
yield AlexaModeController(
self.entity, instance=f"{remote.DOMAIN}.{remote.ATTR_ACTIVITY}"
)
@@ -692,7 +703,9 @@ class HumidifierCapabilities(AlexaEntity):
"""Yield the supported interfaces."""
yield AlexaPowerController(self.entity)
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
if supported & humidifier.HumidifierEntityFeature.MODES:
if (
supported & humidifier.HumidifierEntityFeature.MODES
) and self.entity.attributes.get(humidifier.ATTR_AVAILABLE_MODES):
yield AlexaModeController(
self.entity, instance=f"{humidifier.DOMAIN}.{humidifier.ATTR_MODE}"
)

View File

@@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "bronze",
"requirements": ["aioamazondevices==3.2.2"]
"requirements": ["aioamazondevices==3.5.1"]
}

View File

@@ -13,6 +13,6 @@
"integration_type": "system",
"iot_class": "cloud_push",
"loggers": ["acme", "hass_nabucasa", "snitun"],
"requirements": ["hass-nabucasa==0.104.0"],
"requirements": ["hass-nabucasa==0.106.0"],
"single_config_entry": true
}

View File

@@ -8,7 +8,7 @@
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
"iot_class": "local_push",
"loggers": ["async_upnp_client"],
"requirements": ["async-upnp-client==0.44.0", "getmac==0.9.5"],
"requirements": ["async-upnp-client==0.45.0", "getmac==0.9.5"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaRenderer:1",

View File

@@ -7,7 +7,7 @@
"dependencies": ["ssdp"],
"documentation": "https://www.home-assistant.io/integrations/dlna_dms",
"iot_class": "local_polling",
"requirements": ["async-upnp-client==0.44.0"],
"requirements": ["async-upnp-client==0.45.0"],
"ssdp": [
{
"deviceType": "urn:schemas-upnp-org:device:MediaServer:1",

View File

@@ -63,6 +63,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: EnphaseConfigEntry) ->
coordinator = entry.runtime_data
coordinator.async_cancel_token_refresh()
coordinator.async_cancel_firmware_refresh()
coordinator.async_cancel_mac_verification()
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

View File

@@ -7,7 +7,7 @@
"iot_class": "local_polling",
"loggers": ["pyenphase"],
"quality_scale": "platinum",
"requirements": ["pyenphase==2.1.0"],
"requirements": ["pyenphase==2.2.2"],
"zeroconf": [
{
"type": "_enphase-envoy._tcp.local."

View File

@@ -171,14 +171,19 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
for device in new_data.devices.values():
# create device registry entry for new main devices
if (
device.ain not in self.data.devices
and device.device_and_unit_id[1] is None
if device.ain not in self.data.devices and (
device.device_and_unit_id[1] is None
or (
# workaround for sub units without a main device, e.g. Energy 250
# https://github.com/home-assistant/core/issues/145204
device.device_and_unit_id[1] == "1"
and device.device_and_unit_id[0] not in new_data.devices
)
):
dr.async_get(self.hass).async_get_or_create(
config_entry_id=self.config_entry.entry_id,
name=device.name,
identifiers={(DOMAIN, device.ain)},
identifiers={(DOMAIN, device.device_and_unit_id[0])},
manufacturer=device.manufacturer,
model=device.productname,
sw_version=device.fw_version,

View File

@@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20250702.0"]
"requirements": ["home-assistant-frontend==20250702.3"]
}

View File

@@ -15,6 +15,7 @@ from homeassistant.components.climate import (
FAN_HIGH,
FAN_LOW,
FAN_MEDIUM,
FAN_OFF,
SWING_BOTH,
SWING_HORIZONTAL,
SWING_OFF,
@@ -31,6 +32,7 @@ from .coordinator import FGLairConfigEntry, FGLairCoordinator
from .entity import FGLairEntity
HA_TO_FUJI_FAN = {
FAN_OFF: FanSpeed.QUIET,
FAN_LOW: FanSpeed.LOW,
FAN_MEDIUM: FanSpeed.MEDIUM,
FAN_HIGH: FanSpeed.HIGH,

View File

@@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"loggers": ["dacite", "gios"],
"requirements": ["gios==6.0.0"]
"requirements": ["gios==6.1.2"]
}

View File

@@ -306,6 +306,11 @@ class WebRTCProvider(CameraWebRTCProvider):
await self.teardown()
raise HomeAssistantError("Camera has no stream source")
if camera.platform.platform_name == "generic":
# This is a workaround to use ffmpeg for generic cameras
# A proper fix will be added in the future together with supporting multiple streams per camera
stream_source = "ffmpeg:" + stream_source
if not self.async_is_supported(stream_source):
await self.teardown()
raise HomeAssistantError("Stream source is not supported by go2rtc")

View File

@@ -127,7 +127,7 @@ class GoogleCloudSpeechToTextEntity(SpeechToTextEntity):
try:
responses = await self._client.streaming_recognize(
requests=request_generator(),
timeout=10,
timeout=30,
retry=AsyncRetry(initial=0.1, maximum=2.0, multiplier=2.0),
)

View File

@@ -218,7 +218,7 @@ class BaseGoogleCloudProvider:
response = await self._client.synthesize_speech(
request,
timeout=10,
timeout=30,
retry=AsyncRetry(initial=0.1, maximum=2.0, multiplier=2.0),
)

View File

@@ -7,5 +7,5 @@
"iot_class": "cloud_polling",
"loggers": ["habiticalib"],
"quality_scale": "platinum",
"requirements": ["habiticalib==0.4.0"]
"requirements": ["habiticalib==0.4.1"]
}

View File

@@ -1,3 +1 @@
"""The hddtemp component."""
DOMAIN = "hddtemp"

View File

@@ -22,14 +22,11 @@ from homeassistant.const import (
CONF_PORT,
UnitOfTemperature,
)
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN
_LOGGER = logging.getLogger(__name__)
ATTR_DEVICE = "device"
@@ -59,21 +56,6 @@ def setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the HDDTemp sensor."""
create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_system_packages_yaml_integration_{DOMAIN}",
breaks_in_ha_version="2025.12.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="deprecated_system_packages_yaml_integration",
translation_placeholders={
"domain": DOMAIN,
"integration_title": "hddtemp",
},
)
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)

View File

@@ -41,7 +41,12 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr, issue_registry as ir
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import API_DEFAULT_RETRY_AFTER, APPLIANCES_WITH_PROGRAMS, DOMAIN
from .const import (
API_DEFAULT_RETRY_AFTER,
APPLIANCES_WITH_PROGRAMS,
BSH_OPERATION_STATE_PAUSE,
DOMAIN,
)
from .utils import get_dict_from_home_connect_error
_LOGGER = logging.getLogger(__name__)
@@ -66,6 +71,7 @@ class HomeConnectApplianceData:
def update(self, other: HomeConnectApplianceData) -> None:
"""Update data with data from other instance."""
self.commands.clear()
self.commands.update(other.commands)
self.events.update(other.events)
self.info.connected = other.info.connected
@@ -201,6 +207,28 @@ class HomeConnectCoordinator(
raw_key=status_key.value,
value=event.value,
)
if (
status_key == StatusKey.BSH_COMMON_OPERATION_STATE
and event.value == BSH_OPERATION_STATE_PAUSE
and CommandKey.BSH_COMMON_RESUME_PROGRAM
not in (
commands := self.data[
event_message_ha_id
].commands
)
):
# All the appliances that can be paused
# should have the resume command available.
commands.add(CommandKey.BSH_COMMON_RESUME_PROGRAM)
for (
listener,
context,
) in self._special_listeners.values():
if (
EventKey.BSH_COMMON_APPLIANCE_DEPAIRED
not in context
):
listener()
self._call_event_listener(event_message)
case EventType.NOTIFY:
@@ -627,10 +655,7 @@ class HomeConnectCoordinator(
"times": str(MAX_EXECUTIONS),
"time_window": str(MAX_EXECUTIONS_TIME_WINDOW // 60),
"home_connect_resource_url": "https://www.home-connect.com/global/help-support/error-codes#/Togglebox=15362315-13320636-1/",
"home_assistant_core_new_issue_url": (
"https://github.com/home-assistant/core/issues/new?template=bug_report.yml"
f"&integration_name={DOMAIN}&integration_link=https://www.home-assistant.io/integrations/{DOMAIN}/"
),
"home_assistant_core_issue_url": "https://github.com/home-assistant/core/issues/147299",
},
)
return True

View File

@@ -130,7 +130,7 @@
"step": {
"confirm": {
"title": "[%key:component::home_connect::issues::home_connect_too_many_connected_paired_events::title%]",
"description": "The appliance \"{appliance_name}\" has been reported as connected or paired {times} times in less than {time_window} minutes, so refreshes on connected or paired events has been disabled to avoid exceeding the API rate limit.\n\nPlease refer to the [Home Connect Wi-Fi requirements and recommendations]({home_connect_resource_url}). If everything seems right with your network configuration, restart the appliance.\n\nClick \"submit\" to re-enable the updates.\nIf the issue persists, please create an issue in the [Home Assistant core repository]({home_assistant_core_new_issue_url})."
"description": "The appliance \"{appliance_name}\" has been reported as connected or paired {times} times in less than {time_window} minutes, so refreshes on connected or paired events has been disabled to avoid exceeding the API rate limit.\n\nPlease refer to the [Home Connect Wi-Fi requirements and recommendations]({home_connect_resource_url}). If everything seems right with your network configuration, restart the appliance.\n\nClick \"submit\" to re-enable the updates.\nIf the issue persists, please see the following issue in the [Home Assistant core repository]({home_assistant_core_issue_url})."
}
}
}

View File

@@ -113,9 +113,7 @@ class HomematicipHAP:
self._ws_close_requested = False
self._ws_connection_closed = asyncio.Event()
self._retry_task: asyncio.Task | None = None
self._tries = 0
self._accesspoint_connected = True
self._get_state_task: asyncio.Task | None = None
self.hmip_device_by_entity_id: dict[str, Any] = {}
self.reset_connection_listener: Callable | None = None
@@ -161,17 +159,8 @@ class HomematicipHAP:
"""
if not self.home.connected:
_LOGGER.error("HMIP access point has lost connection with the cloud")
self._accesspoint_connected = False
self._ws_connection_closed.set()
self.set_all_to_unavailable()
elif not self._accesspoint_connected:
# Now the HOME_CHANGED event has fired indicating the access
# point has reconnected to the cloud again.
# Explicitly getting an update as entity states might have
# changed during access point disconnect."""
job = self.hass.async_create_task(self.get_state())
job.add_done_callback(self.get_state_finished)
self._accesspoint_connected = True
@callback
def async_create_entity(self, *args, **kwargs) -> None:
@@ -185,20 +174,43 @@ class HomematicipHAP:
await asyncio.sleep(30)
await self.hass.config_entries.async_reload(self.config_entry.entry_id)
async def _try_get_state(self) -> None:
"""Call get_state in a loop until no error occurs, using exponential backoff on error."""
# Wait until WebSocket connection is established.
while not self.home.websocket_is_connected():
await asyncio.sleep(2)
delay = 8
max_delay = 1500
while True:
try:
await self.get_state()
break
except HmipConnectionError as err:
_LOGGER.warning(
"Get_state failed, retrying in %s seconds: %s", delay, err
)
await asyncio.sleep(delay)
delay = min(delay * 2, max_delay)
async def get_state(self) -> None:
"""Update HMIP state and tell Home Assistant."""
await self.home.get_current_state_async()
self.update_all()
def get_state_finished(self, future) -> None:
"""Execute when get_state coroutine has finished."""
"""Execute when try_get_state coroutine has finished."""
try:
future.result()
except HmipConnectionError:
# Somehow connection could not recover. Will disconnect and
# so reconnect loop is taking over.
_LOGGER.error("Updating state after HMIP access point reconnect failed")
self.hass.async_create_task(self.home.disable_events())
except Exception as err: # noqa: BLE001
_LOGGER.error(
"Error updating state after HMIP access point reconnect: %s", err
)
else:
_LOGGER.info(
"Updating state after HMIP access point reconnect finished successfully",
)
def set_all_to_unavailable(self) -> None:
"""Set all devices to unavailable and tell Home Assistant."""
@@ -222,8 +234,8 @@ class HomematicipHAP:
async def async_reset(self) -> bool:
"""Close the websocket connection."""
self._ws_close_requested = True
if self._retry_task is not None:
self._retry_task.cancel()
if self._get_state_task is not None:
self._get_state_task.cancel()
await self.home.disable_events_async()
_LOGGER.debug("Closed connection to HomematicIP cloud server")
await self.hass.config_entries.async_unload_platforms(
@@ -247,7 +259,9 @@ class HomematicipHAP:
"""Handle websocket connected."""
_LOGGER.info("Websocket connection to HomematicIP Cloud established")
if self._ws_connection_closed.is_set():
await self.get_state()
self._get_state_task = self.hass.async_create_task(self._try_get_state())
self._get_state_task.add_done_callback(self.get_state_finished)
self._ws_connection_closed.clear()
async def ws_disconnected_handler(self) -> None:
@@ -256,11 +270,12 @@ class HomematicipHAP:
self._ws_connection_closed.set()
async def ws_reconnected_handler(self, reason: str) -> None:
"""Handle websocket reconnection."""
"""Handle websocket reconnection. Is called when Websocket tries to reconnect."""
_LOGGER.info(
"Websocket connection to HomematicIP Cloud re-established due to reason: %s",
"Websocket connection to HomematicIP Cloud trying to reconnect due to reason: %s",
reason,
)
self._ws_connection_closed.set()
async def get_hap(

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/homematicip_cloud",
"iot_class": "cloud_push",
"loggers": ["homematicip"],
"requirements": ["homematicip==2.0.6"]
"requirements": ["homematicip==2.0.7"]
}

View File

@@ -8,5 +8,5 @@
"iot_class": "local_polling",
"loggers": ["aioimmich"],
"quality_scale": "silver",
"requirements": ["aioimmich==0.10.1"]
"requirements": ["aioimmich==0.10.2"]
}

View File

@@ -44,7 +44,7 @@ class ImmichUpdateEntity(ImmichEntity, UpdateEntity):
return self.coordinator.data.server_about.version
@property
def latest_version(self) -> str:
def latest_version(self) -> str | None:
"""Available new immich server version."""
assert self.coordinator.data.server_version_check
return self.coordinator.data.server_version_check.release_version

View File

@@ -23,7 +23,7 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from .const import CONF_USE_BLUETOOTH, DOMAIN
from .coordinator import (
@@ -57,11 +57,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: LaMarzoccoConfigEntry) -
assert entry.unique_id
serial = entry.unique_id
client = async_get_clientsession(hass)
cloud_client = LaMarzoccoCloudClient(
username=entry.data[CONF_USERNAME],
password=entry.data[CONF_PASSWORD],
client=client,
client=async_create_clientsession(hass),
)
try:

View File

@@ -66,7 +66,7 @@ ENTITIES: tuple[LaMarzoccoBinarySensorEntityDescription, ...] = (
WidgetType.CM_BACK_FLUSH, BackFlush(status=BackFlushStatus.OFF)
),
).status
is BackFlushStatus.REQUESTED
in (BackFlushStatus.REQUESTED, BackFlushStatus.CLEANING)
),
entity_category=EntityCategory.DIAGNOSTIC,
supported_fn=lambda coordinator: (

View File

@@ -33,7 +33,7 @@ from homeassistant.const import (
)
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant.helpers.selector import (
SelectOptionDict,
SelectSelector,
@@ -83,7 +83,7 @@ class LmConfigFlow(ConfigFlow, domain=DOMAIN):
**user_input,
}
self._client = async_get_clientsession(self.hass)
self._client = async_create_clientsession(self.hass)
cloud_client = LaMarzoccoCloudClient(
username=data[CONF_USERNAME],
password=data[CONF_PASSWORD],

View File

@@ -37,5 +37,5 @@
"iot_class": "cloud_push",
"loggers": ["pylamarzocco"],
"quality_scale": "platinum",
"requirements": ["pylamarzocco==2.0.9"]
"requirements": ["pylamarzocco==2.0.11"]
}

View File

@@ -10,6 +10,9 @@ import aiolifx_effects as aiolifx_effects_module
import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_BRIGHTNESS_STEP,
ATTR_BRIGHTNESS_STEP_PCT,
ATTR_EFFECT,
ATTR_TRANSITION,
LIGHT_TURN_ON_SCHEMA,
@@ -234,6 +237,20 @@ class LIFXLight(LIFXEntity, LightEntity):
else:
fade = 0
if ATTR_BRIGHTNESS_STEP in kwargs or ATTR_BRIGHTNESS_STEP_PCT in kwargs:
brightness = self.brightness if self.is_on and self.brightness else 0
if ATTR_BRIGHTNESS_STEP in kwargs:
brightness += kwargs.pop(ATTR_BRIGHTNESS_STEP)
else:
brightness_pct = round(brightness / 255 * 100)
brightness = round(
(brightness_pct + kwargs.pop(ATTR_BRIGHTNESS_STEP_PCT)) / 100 * 255
)
kwargs[ATTR_BRIGHTNESS] = max(0, min(255, brightness))
# These are both False if ATTR_POWER is not set
power_on = kwargs.get(ATTR_POWER, False)
power_off = not kwargs.get(ATTR_POWER, True)

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
from typing import Any
from chip.clusters import Objects as clusters
from chip.clusters.Objects import NullValue
from matter_server.client.models import device_types
from homeassistant.components.light import (
@@ -241,7 +242,7 @@ class MatterLight(MatterEntity, LightEntity):
return int(color_temp)
def _get_brightness(self) -> int:
def _get_brightness(self) -> int | None:
"""Get brightness from matter."""
level_control = self._endpoint.get_cluster(clusters.LevelControl)
@@ -255,6 +256,10 @@ class MatterLight(MatterEntity, LightEntity):
self.entity_id,
)
if level_control.currentLevel is NullValue:
# currentLevel is a nullable value.
return None
return round(
renormalize(
level_control.currentLevel,

View File

@@ -26,14 +26,6 @@ class OAuth2FlowHandler(
"""Return logger."""
return logging.getLogger(__name__)
@property
def extra_authorize_data(self) -> dict:
"""Extra data that needs to be appended to the authorize url."""
# "vg" is mandatory but the value doesn't seem to matter
return {
"vg": "sv-SE",
}
async def async_step_reauth(
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:

View File

@@ -21,5 +21,5 @@
"documentation": "https://www.home-assistant.io/integrations/motion_blinds",
"iot_class": "local_push",
"loggers": ["motionblinds"],
"requirements": ["motionblinds==0.6.28"]
"requirements": ["motionblinds==0.6.29"]
}

View File

@@ -2114,6 +2114,9 @@ def data_schema_from_fields(
if schema_section is None:
data_schema.update(data_schema_element)
continue
if not data_schema_element:
# Do not show empty sections
continue
collapsed = (
not any(
(default := data_schema_fields[str(option)].default) is vol.UNDEFINED

View File

@@ -389,16 +389,6 @@ def async_setup_entity_entry_helper(
_async_setup_entities()
def init_entity_id_from_config(
hass: HomeAssistant, entity: Entity, config: ConfigType, entity_id_format: str
) -> None:
"""Set entity_id from object_id if defined in config."""
if CONF_OBJECT_ID in config:
entity.entity_id = async_generate_entity_id(
entity_id_format, config[CONF_OBJECT_ID], None, hass
)
class MqttAttributesMixin(Entity):
"""Mixin used for platforms that support JSON attributes."""
@@ -1312,6 +1302,7 @@ class MqttEntity(
_attr_should_poll = False
_default_name: str | None
_entity_id_format: str
_update_registry_entity_id: str | None = None
def __init__(
self,
@@ -1346,13 +1337,33 @@ class MqttEntity(
def _init_entity_id(self) -> None:
"""Set entity_id from object_id if defined in config."""
init_entity_id_from_config(
self.hass, self, self._config, self._entity_id_format
if CONF_OBJECT_ID not in self._config:
return
self.entity_id = async_generate_entity_id(
self._entity_id_format, self._config[CONF_OBJECT_ID], None, self.hass
)
if self.unique_id is None:
return
# Check for previous deleted entities
entity_registry = er.async_get(self.hass)
entity_platform = self._entity_id_format.split(".")[0]
if (
deleted_entry := entity_registry.deleted_entities.get(
(entity_platform, DOMAIN, self.unique_id)
)
) and deleted_entry.entity_id != self.entity_id:
# Plan to update the entity_id basis on `object_id` if a deleted entity was found
self._update_registry_entity_id = self.entity_id
@final
async def async_added_to_hass(self) -> None:
"""Subscribe to MQTT events."""
if self._update_registry_entity_id is not None:
entity_registry = er.async_get(self.hass)
entity_registry.async_update_entity(
self.entity_id, new_entity_id=self._update_registry_entity_id
)
await super().async_added_to_hass()
self._subscriptions = {}
self._prepare_subscribe_topics()

View File

@@ -98,6 +98,12 @@ def validate_sensor_state_and_device_class_config(config: ConfigType) -> ConfigT
f"together with state class `{state_class}`"
)
unit_of_measurement: str | None
if (
unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)
) is not None and not unit_of_measurement.strip():
config.pop(CONF_UNIT_OF_MEASUREMENT)
# Only allow `options` to be set for `enum` sensors
# to limit the possible sensor values
if (options := config.get(CONF_OPTIONS)) is not None:

View File

@@ -7,6 +7,6 @@
"documentation": "https://www.home-assistant.io/integrations/music_assistant",
"iot_class": "local_push",
"loggers": ["music_assistant"],
"requirements": ["music-assistant-client==1.2.3"],
"requirements": ["music-assistant-client==1.2.4"],
"zeroconf": ["_mass._tcp.local."]
}

View File

@@ -248,8 +248,6 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity):
player = self.player
active_queue = self.active_queue
# update generic attributes
if player.powered and active_queue is not None:
self._attr_state = MediaPlayerState(active_queue.state.value)
if player.powered and player.playback_state is not None:
self._attr_state = MediaPlayerState(player.playback_state.value)
else:

View File

@@ -39,6 +39,7 @@ class BinarySensor(CoilEntity, BinarySensorEntity):
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
"""Initialize entity."""
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
self._on_value = coil.get_mapping_for(1)
def _async_read_coil(self, data: CoilData) -> None:
self._attr_is_on = data.value == "ON"
self._attr_is_on = data.value == self._on_value

View File

@@ -41,14 +41,16 @@ class Switch(CoilEntity, SwitchEntity):
def __init__(self, coordinator: CoilCoordinator, coil: Coil) -> None:
"""Initialize entity."""
super().__init__(coordinator, coil, ENTITY_ID_FORMAT)
self._on_value = coil.get_mapping_for(1)
self._off_value = coil.get_mapping_for(0)
def _async_read_coil(self, data: CoilData) -> None:
self._attr_is_on = data.value == "ON"
self._attr_is_on = data.value == self._on_value
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self._async_write_coil("ON")
await self._async_write_coil(self._on_value)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
await self._async_write_coil("OFF")
await self._async_write_coil(self._off_value)

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/nyt_games",
"integration_type": "service",
"iot_class": "cloud_polling",
"requirements": ["nyt_games==0.4.4"]
"requirements": ["nyt_games==0.5.0"]
}

View File

@@ -218,6 +218,9 @@ def _async_fix_device_id(
for device_entry in device_entries:
unique_id = str(next(iter(device_entry.identifiers))[1])
device_entry_map[unique_id] = device_entry
if unique_id.startswith(mac_address):
# Already in the correct format
continue
if (suffix := unique_id.removeprefix(str(serial_number))) != unique_id:
migrations[unique_id] = f"{mac_address}{suffix}"

View File

@@ -0,0 +1,12 @@
"""Specifies the parameter for the httpx download."""
from httpx import AsyncClient, Response, Timeout
async def get_calendar(client: AsyncClient, url: str) -> Response:
"""Make an HTTP GET request using Home Assistant's async HTTPX client with timeout."""
return await client.get(
url,
follow_redirects=True,
timeout=Timeout(5, read=30, write=5, pool=5),
)

View File

@@ -4,13 +4,14 @@ from http import HTTPStatus
import logging
from typing import Any
from httpx import HTTPError, InvalidURL
from httpx import HTTPError, InvalidURL, TimeoutException
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_URL
from homeassistant.helpers.httpx_client import get_async_client
from .client import get_calendar
from .const import CONF_CALENDAR_NAME, DOMAIN
from .ics import InvalidIcsException, parse_calendar
@@ -49,7 +50,7 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
self._async_abort_entries_match({CONF_URL: user_input[CONF_URL]})
client = get_async_client(self.hass)
try:
res = await client.get(user_input[CONF_URL], follow_redirects=True)
res = await get_calendar(client, user_input[CONF_URL])
if res.status_code == HTTPStatus.FORBIDDEN:
errors["base"] = "forbidden"
return self.async_show_form(
@@ -58,9 +59,14 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
errors=errors,
)
res.raise_for_status()
except TimeoutException as err:
errors["base"] = "timeout_connect"
_LOGGER.debug(
"A timeout error occurred: %s", str(err) or type(err).__name__
)
except (HTTPError, InvalidURL) as err:
errors["base"] = "cannot_connect"
_LOGGER.debug("An error occurred: %s", err)
_LOGGER.debug("An error occurred: %s", str(err) or type(err).__name__)
else:
try:
await parse_calendar(self.hass, res.text)

View File

@@ -3,7 +3,7 @@
from datetime import timedelta
import logging
from httpx import HTTPError, InvalidURL
from httpx import HTTPError, InvalidURL, TimeoutException
from ical.calendar import Calendar
from homeassistant.config_entries import ConfigEntry
@@ -12,6 +12,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.httpx_client import get_async_client
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .client import get_calendar
from .const import DOMAIN
from .ics import InvalidIcsException, parse_calendar
@@ -36,7 +37,7 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
name=f"{DOMAIN}_{config_entry.title}",
update_interval=SCAN_INTERVAL,
always_update=True,
)
@@ -46,13 +47,19 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
async def _async_update_data(self) -> Calendar:
"""Update data from the url."""
try:
res = await self._client.get(self._url, follow_redirects=True)
res = await get_calendar(self._client, self._url)
res.raise_for_status()
except TimeoutException as err:
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="timeout",
) from err
except (HTTPError, InvalidURL) as err:
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="unable_to_fetch",
translation_placeholders={"err": str(err)},
) from err
try:
self.ics = res.text

View File

@@ -18,14 +18,18 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
},
"error": {
"timeout_connect": "[%key:common::config_flow::error::timeout_connect%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"forbidden": "The server understood the request but refuses to authorize it.",
"invalid_ics_file": "There was a problem reading the calendar information. See the error log for additional details."
}
},
"exceptions": {
"timeout": {
"message": "The connection timed out. See the debug log for additional details."
},
"unable_to_fetch": {
"message": "Unable to fetch calendar data: {err}"
"message": "Unable to fetch calendar data. See the debug log for additional details."
},
"unable_to_parse": {
"message": "Unable to parse calendar data: {err}"

View File

@@ -196,7 +196,7 @@ class RensonFan(RensonEntity, FanEntity):
all_data = self.coordinator.data
breeze_temp = self.api.get_field_value(all_data, BREEZE_TEMPERATURE_FIELD)
await self.hass.async_add_executor_job(
self.api.set_breeze, cmd.name, breeze_temp, True
self.api.set_breeze, cmd, breeze_temp, True
)
else:
await self.hass.async_add_executor_job(self.api.set_manual_level, cmd)

View File

@@ -49,7 +49,7 @@ class RestData:
# Convert auth tuple to aiohttp.BasicAuth if needed
if isinstance(auth, tuple) and len(auth) == 2:
self._auth: aiohttp.BasicAuth | aiohttp.DigestAuthMiddleware | None = (
aiohttp.BasicAuth(auth[0], auth[1])
aiohttp.BasicAuth(auth[0], auth[1], encoding="utf-8")
)
else:
self._auth = auth
@@ -115,6 +115,16 @@ class RestData:
for key, value in rendered_params.items():
if isinstance(value, bool):
rendered_params[key] = str(value).lower()
elif not isinstance(value, (str, int, float, type(None))):
# For backward compatibility with httpx behavior, convert non-primitive
# types to strings. This maintains compatibility after switching from
# httpx to aiohttp. See https://github.com/home-assistant/core/issues/148153
_LOGGER.debug(
"REST query parameter '%s' has type %s, converting to string",
key,
type(value).__name__,
)
rendered_params[key] = str(value)
_LOGGER.debug("Updating from %s", self._resource)
# Create request kwargs
@@ -140,7 +150,14 @@ class RestData:
self._method, self._resource, **request_kwargs
) as response:
# Read the response
self.data = await response.text(encoding=self._encoding)
# Only use configured encoding if no charset in Content-Type header
# If charset is present in Content-Type, let aiohttp use it
if response.charset:
# Let aiohttp use the charset from Content-Type header
self.data = await response.text()
else:
# Use configured encoding as fallback
self.data = await response.text(encoding=self._encoding)
self.headers = response.headers
except TimeoutError as ex:

View File

@@ -178,6 +178,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
)
if not service.return_response:
# always read the response to avoid closing the connection
# before the server has finished sending it, while avoiding excessive memory usage
async for _ in response.content.iter_chunked(1024):
pass
return None
_content = None

View File

@@ -124,6 +124,7 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
self._model: str | None = None
self._connect_result: str | None = None
self._method: str | None = None
self._port: int | None = None
self._name: str | None = None
self._title: str = ""
self._id: int | None = None
@@ -199,33 +200,37 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
async def _async_create_bridge(self) -> None:
"""Create the bridge."""
result, method, _info = await self._async_get_device_info_and_method()
result = await self._async_load_device_info()
if result not in SUCCESSFUL_RESULTS:
LOGGER.debug("No working config found for %s", self._host)
raise AbortFlow(result)
assert method is not None
self._bridge = SamsungTVBridge.get_bridge(self.hass, method, self._host)
assert self._method is not None
self._bridge = SamsungTVBridge.get_bridge(
self.hass, self._method, self._host, self._port
)
async def _async_get_device_info_and_method(
async def _async_load_device_info(
self,
) -> tuple[str, str | None, dict[str, Any] | None]:
) -> str:
"""Get device info and method only once."""
if self._connect_result is None:
result, _, method, info = await async_get_device_info(self.hass, self._host)
result, port, method, info = await async_get_device_info(
self.hass, self._host
)
self._connect_result = result
self._method = method
self._port = port
self._device_info = info
if not method:
LOGGER.debug("Host:%s did not return device info", self._host)
return result, None, None
return self._connect_result, self._method, self._device_info
return self._connect_result
async def _async_get_and_check_device_info(self) -> bool:
"""Try to get the device info."""
result, _method, info = await self._async_get_device_info_and_method()
result = await self._async_load_device_info()
if result not in SUCCESSFUL_RESULTS:
raise AbortFlow(result)
if not info:
if not (info := self._device_info):
return False
dev_info = info.get("device", {})
assert dev_info is not None

View File

@@ -40,7 +40,7 @@
"samsungctl[websocket]==0.7.1",
"samsungtvws[async,encrypted]==2.7.2",
"wakeonlan==3.1.0",
"async-upnp-client==0.44.0"
"async-upnp-client==0.45.0"
],
"ssdp": [
{

View File

@@ -5,5 +5,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/schlage",
"iot_class": "cloud_polling",
"requirements": ["pyschlage==2025.4.0"]
"requirements": ["pyschlage==2025.7.2"]
}

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/sharkiq",
"iot_class": "cloud_polling",
"loggers": ["sharkiq"],
"requirements": ["sharkiq==1.1.0"]
"requirements": ["sharkiq==1.1.1"]
}

View File

@@ -9,7 +9,7 @@
"iot_class": "local_push",
"loggers": ["aioshelly"],
"quality_scale": "silver",
"requirements": ["aioshelly==13.7.1"],
"requirements": ["aioshelly==13.7.2"],
"zeroconf": [
{
"type": "_http._tcp.local.",

View File

@@ -868,8 +868,8 @@ RPC_SENSORS: Final = {
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
device_class=SensorDeviceClass.CURRENT,
state_class=SensorStateClass.MEASUREMENT,
available=lambda status: (status and status["n_current"]) is not None,
removal_condition=lambda _config, status, _key: "n_current" not in status,
removal_condition=lambda _config, status, key: status[key].get("n_current")
is None,
entity_registry_enabled_default=False,
),
"total_current": RpcSensorDescription(

View File

@@ -30,5 +30,5 @@
"iot_class": "cloud_push",
"loggers": ["pysmartthings"],
"quality_scale": "bronze",
"requirements": ["pysmartthings==3.2.5"]
"requirements": ["pysmartthings==3.2.8"]
}

View File

@@ -18,6 +18,11 @@ from .entity import SmartThingsEntity
LAMP_TO_HA = {
"extraHigh": "extra_high",
"high": "high",
"mid": "mid",
"low": "low",
"on": "on",
"off": "off",
}
WASHER_SOIL_LEVEL_TO_HA = {

View File

@@ -12,7 +12,7 @@
"integration_type": "device",
"iot_class": "local_push",
"quality_scale": "silver",
"requirements": ["pysmlight==0.2.6"],
"requirements": ["pysmlight==0.2.7"],
"zeroconf": [
{
"type": "_slzb-06._tcp.local."

View File

@@ -38,7 +38,7 @@ BINARY_SENSOR_DESCRIPTIONS: list[SnooBinarySensorEntityDescription] = [
SnooBinarySensorEntityDescription(
key="right_clip",
translation_key="right_clip",
value_fn=lambda data: data.left_safety_clip,
value_fn=lambda data: data.right_safety_clip,
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_category=EntityCategory.DIAGNOSTIC,
),

View File

@@ -72,7 +72,7 @@ class SonosFavorites(SonosHouseholdCoordinator):
"""Process the event payload in an async lock and update entities."""
event_id = event.variables["favorites_update_id"]
container_ids = event.variables["container_update_i_ds"]
if not (match := re.search(r"FV:2,(\d+)", container_ids)):
if not container_ids or not (match := re.search(r"FV:2,(\d+)", container_ids)):
return
container_id = int(match.groups()[0])

View File

@@ -221,12 +221,16 @@ def _get_item_thumbnail(
) -> str | None:
"""Construct path to thumbnail image."""
item_thumbnail: str | None = None
if artwork_track_id := item.get("artwork_track_id"):
track_id = item.get("artwork_track_id") or (
item.get("id") if item_type == "track" else None
)
if track_id:
if internal_request:
item_thumbnail = player.generate_image_url_from_track_id(artwork_track_id)
item_thumbnail = player.generate_image_url_from_track_id(track_id)
elif item_type is not None:
item_thumbnail = entity.get_browse_image_url(
item_type, item["id"], artwork_track_id
item_type, item["id"], track_id
)
elif search_type in ["apps", "radios"]:
@@ -311,8 +315,7 @@ async def build_item_response(
title=item["title"],
media_content_type=item_type,
media_class=CONTENT_TYPE_MEDIA_CLASS[item_type]["item"],
can_expand=CONTENT_TYPE_MEDIA_CLASS[item_type]["children"]
is not None,
can_expand=bool(CONTENT_TYPE_MEDIA_CLASS[item_type]["children"]),
can_play=True,
)

View File

@@ -8,5 +8,5 @@
"iot_class": "local_push",
"loggers": ["async_upnp_client"],
"quality_scale": "internal",
"requirements": ["async-upnp-client==0.44.0"]
"requirements": ["async-upnp-client==0.45.0"]
}

View File

@@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["pysuez", "regex"],
"quality_scale": "bronze",
"requirements": ["pysuezV2==2.0.5"]
"requirements": ["pysuezV2==2.0.7"]
}

View File

@@ -41,5 +41,5 @@
"iot_class": "local_push",
"loggers": ["switchbot"],
"quality_scale": "gold",
"requirements": ["PySwitchbot==0.67.0"]
"requirements": ["PySwitchbot==0.68.2"]
}

View File

@@ -113,11 +113,11 @@ SENSOR_DESCRIPTIONS_BY_DEVICE_TYPES = {
),
"Plug Mini (US)": (
VOLTAGE_DESCRIPTION,
CURRENT_DESCRIPTION_IN_A,
CURRENT_DESCRIPTION_IN_MA,
),
"Plug Mini (JP)": (
VOLTAGE_DESCRIPTION,
CURRENT_DESCRIPTION_IN_A,
CURRENT_DESCRIPTION_IN_MA,
),
"Hub 2": (
TEMPERATURE_DESCRIPTION,

View File

@@ -28,6 +28,7 @@ class SyncthruCoordinator(DataUpdateCoordinator[SyncThru]):
hass,
_LOGGER,
name=DOMAIN,
config_entry=entry,
update_interval=timedelta(seconds=30),
)
self.syncthru = SyncThru(

View File

@@ -374,9 +374,7 @@ class TelegramNotificationService:
}
if data is not None:
if ATTR_PARSER in data:
params[ATTR_PARSER] = self._parsers.get(
data[ATTR_PARSER], self.parse_mode
)
params[ATTR_PARSER] = data[ATTR_PARSER]
if ATTR_TIMEOUT in data:
params[ATTR_TIMEOUT] = data[ATTR_TIMEOUT]
if ATTR_DISABLE_NOTIF in data:
@@ -408,6 +406,8 @@ class TelegramNotificationService:
params[ATTR_REPLYMARKUP] = InlineKeyboardMarkup(
[_make_row_inline_keyboard(row) for row in keys]
)
if params[ATTR_PARSER] == PARSER_PLAIN_TEXT:
params[ATTR_PARSER] = None
return params
async def _send_msg(

View File

@@ -159,8 +159,6 @@ class OptionsFlowHandler(OptionsFlow):
"""Manage the options."""
if user_input is not None:
if user_input[ATTR_PARSER] == PARSER_PLAIN_TEXT:
user_input[ATTR_PARSER] = None
return self.async_create_entry(data=user_input)
return self.async_show_form(

View File

@@ -109,6 +109,7 @@ send_photo:
- "markdown"
- "markdownv2"
- "plain_text"
translation_key: "parse_mode"
disable_notification:
selector:
boolean:
@@ -261,6 +262,7 @@ send_animation:
- "markdown"
- "markdownv2"
- "plain_text"
translation_key: "parse_mode"
disable_notification:
selector:
boolean:
@@ -341,6 +343,7 @@ send_video:
- "markdown"
- "markdownv2"
- "plain_text"
translation_key: "parse_mode"
disable_notification:
selector:
boolean:
@@ -493,6 +496,7 @@ send_document:
- "markdown"
- "markdownv2"
- "plain_text"
translation_key: "parse_mode"
disable_notification:
selector:
boolean:
@@ -670,6 +674,7 @@ edit_message:
- "markdown"
- "markdownv2"
- "plain_text"
translation_key: "parse_mode"
disable_web_page_preview:
selector:
boolean:

View File

@@ -82,7 +82,7 @@ class PushBot(BaseTelegramBot):
self.base_url = config.data.get(CONF_URL) or get_url(
hass, require_ssl=True, allow_internal=False
)
self.webhook_url = f"{self.base_url}{TELEGRAM_WEBHOOK_URL}"
self.webhook_url = self.base_url + _get_webhook_url(bot)
async def shutdown(self) -> None:
"""Shutdown the app."""
@@ -98,9 +98,11 @@ class PushBot(BaseTelegramBot):
api_kwargs={"secret_token": self.secret_token},
connect_timeout=5,
)
except TelegramError:
except TelegramError as err:
retry_num += 1
_LOGGER.warning("Error trying to set webhook (retry #%d)", retry_num)
_LOGGER.warning(
"Error trying to set webhook (retry #%d)", retry_num, exc_info=err
)
return False
@@ -143,7 +145,6 @@ class PushBotView(HomeAssistantView):
"""View for handling webhook calls from Telegram."""
requires_auth = False
url = TELEGRAM_WEBHOOK_URL
name = "telegram_webhooks"
def __init__(
@@ -160,6 +161,7 @@ class PushBotView(HomeAssistantView):
self.application = application
self.trusted_networks = trusted_networks
self.secret_token = secret_token
self.url = _get_webhook_url(bot)
async def post(self, request: HomeAssistantRequest) -> Response | None:
"""Accept the POST from telegram."""
@@ -183,3 +185,7 @@ class PushBotView(HomeAssistantView):
await self.application.process_update(update)
return None
def _get_webhook_url(bot: Bot) -> str:
return f"{TELEGRAM_WEBHOOK_URL}_{bot.id}"

View File

@@ -14,9 +14,8 @@ CONF_REFRESH_TOKEN = "refresh_token"
LOGGER = logging.getLogger(__package__)
CLIENT_ID = "71b813eb-4a2e-483a-b831-4dec5cb9bf0d"
AUTHORIZE_URL = "https://auth.tesla.com/oauth2/v3/authorize"
TOKEN_URL = "https://auth.tesla.com/oauth2/v3/token"
AUTHORIZE_URL = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/authorize"
TOKEN_URL = "https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token"
SCOPES = [
Scope.OPENID,

View File

@@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/tesla_fleet",
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"requirements": ["tesla-fleet-api==1.2.0"]
"requirements": ["tesla-fleet-api==1.2.2"]
}

View File

@@ -125,8 +125,8 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetryBinarySensorEntityDescription, ...] = (
key="charge_state_conn_charge_cable",
polling=True,
polling_value_fn=lambda x: x != "<invalid>",
streaming_listener=lambda vehicle, callback: vehicle.listen_ChargingCableType(
lambda value: callback(value is not None and value != "Unknown")
streaming_listener=lambda vehicle, callback: vehicle.listen_DetailedChargeState(
lambda value: callback(None if value is None else value != "Disconnected")
),
entity_category=EntityCategory.DIAGNOSTIC,
device_class=BinarySensorDeviceClass.CONNECTIVITY,

View File

@@ -14,7 +14,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import TeslemetryConfigEntry
from .entity import TeslemetryVehiclePollingEntity
from .entity import TeslemetryVehicleStreamEntity
from .helpers import handle_command, handle_vehicle_command
from .models import TeslemetryVehicleData
@@ -74,7 +74,7 @@ async def async_setup_entry(
)
class TeslemetryButtonEntity(TeslemetryVehiclePollingEntity, ButtonEntity):
class TeslemetryButtonEntity(TeslemetryVehicleStreamEntity, ButtonEntity):
"""Base class for Teslemetry buttons."""
api: Vehicle

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/teslemetry",
"iot_class": "cloud_polling",
"loggers": ["tesla-fleet-api"],
"requirements": ["tesla-fleet-api==1.2.0", "teslemetry-stream==0.7.9"]
"requirements": ["tesla-fleet-api==1.2.2", "teslemetry-stream==0.7.9"]
}

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/tessie",
"iot_class": "cloud_polling",
"loggers": ["tessie", "tesla-fleet-api"],
"requirements": ["tessie-api==0.1.1", "tesla-fleet-api==1.2.0"]
"requirements": ["tessie-api==0.1.1", "tesla-fleet-api==1.2.2"]
}

View File

@@ -7,7 +7,7 @@
"integration_type": "hub",
"iot_class": "local_push",
"loggers": ["aiounifi"],
"requirements": ["aiounifi==83"],
"requirements": ["aiounifi==84"],
"ssdp": [
{
"manufacturer": "Ubiquiti Networks",

View File

@@ -40,7 +40,7 @@
"integration_type": "hub",
"iot_class": "local_push",
"loggers": ["uiprotect", "unifi_discovery"],
"requirements": ["uiprotect==7.14.1", "unifi-discovery==1.2.0"],
"requirements": ["uiprotect==7.14.2", "unifi-discovery==1.2.0"],
"ssdp": [
{
"manufacturer": "Ubiquiti Networks",

View File

@@ -8,7 +8,7 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["async_upnp_client"],
"requirements": ["async-upnp-client==0.44.0", "getmac==0.9.5"],
"requirements": ["async-upnp-client==0.45.0", "getmac==0.9.5"],
"ssdp": [
{
"st": "urn:schemas-upnp-org:device:InternetGatewayDevice:1"

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/venstar",
"iot_class": "local_polling",
"loggers": ["venstarcolortouch"],
"requirements": ["venstarcolortouch==0.19"]
"requirements": ["venstarcolortouch==0.21"]
}

View File

@@ -11,5 +11,5 @@
"documentation": "https://www.home-assistant.io/integrations/vicare",
"iot_class": "cloud_polling",
"loggers": ["PyViCare"],
"requirements": ["PyViCare==2.44.0"]
"requirements": ["PyViCare==2.50.0"]
}

View File

@@ -98,7 +98,10 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
data = {CONF_HOST: self._host, CONF_CLIENT_SECRET: client.client_key}
if not self._name:
self._name = f"{DEFAULT_NAME} {client.tv_info.system['modelName']}"
if model_name := client.tv_info.system.get("modelName"):
self._name = f"{DEFAULT_NAME} {model_name}"
else:
self._name = DEFAULT_NAME
return self.async_create_entry(title=self._name, data=data)
return self.async_show_form(step_id="pairing", errors=errors)

View File

@@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/webostv",
"iot_class": "local_push",
"loggers": ["aiowebostv"],
"requirements": ["aiowebostv==0.7.3"],
"requirements": ["aiowebostv==0.7.4"],
"ssdp": [
{
"st": "urn:lge-com:service:webos-second-screen:1"

View File

@@ -23,7 +23,7 @@ async def async_setup_entry(
entities: list[WebControlProGenericEntity] = [
WebControlProIdentifyButton(config_entry.entry_id, dest)
for dest in hub.dests.values()
if dest.action(WMS_WebControl_pro_API_actionDescription.Identify)
if dest.hasAction(WMS_WebControl_pro_API_actionDescription.Identify)
]
async_add_entities(entities)

View File

@@ -32,9 +32,9 @@ async def async_setup_entry(
entities: list[WebControlProGenericEntity] = []
for dest in hub.dests.values():
if dest.action(WMS_WebControl_pro_API_actionDescription.AwningDrive):
if dest.hasAction(WMS_WebControl_pro_API_actionDescription.AwningDrive):
entities.append(WebControlProAwning(config_entry.entry_id, dest))
elif dest.action(
elif dest.hasAction(
WMS_WebControl_pro_API_actionDescription.RollerShutterBlindDrive
):
entities.append(WebControlProRollerShutter(config_entry.entry_id, dest))

View File

@@ -33,9 +33,9 @@ async def async_setup_entry(
entities: list[WebControlProGenericEntity] = []
for dest in hub.dests.values():
if dest.action(WMS_WebControl_pro_API_actionDescription.LightDimming):
if dest.hasAction(WMS_WebControl_pro_API_actionDescription.LightDimming):
entities.append(WebControlProDimmer(config_entry.entry_id, dest))
elif dest.action(WMS_WebControl_pro_API_actionDescription.LightSwitch):
elif dest.hasAction(WMS_WebControl_pro_API_actionDescription.LightSwitch):
entities.append(WebControlProLight(config_entry.entry_id, dest))
async_add_entities(entities)

View File

@@ -14,5 +14,5 @@
"documentation": "https://www.home-assistant.io/integrations/wmspro",
"integration_type": "hub",
"iot_class": "local_polling",
"requirements": ["pywmspro==0.3.0"]
"requirements": ["pywmspro==0.3.2"]
}

View File

@@ -6,5 +6,5 @@
"iot_class": "cloud_push",
"loggers": ["pyasn1", "slixmpp"],
"quality_scale": "legacy",
"requirements": ["slixmpp==1.8.5", "emoji==2.8.0"]
"requirements": ["slixmpp==1.10.0", "emoji==2.8.0"]
}

View File

@@ -144,7 +144,8 @@ async def async_send_message( # noqa: C901
self.loop = hass.loop
self.force_starttls = use_tls
self.enable_starttls = use_tls
self.enable_direct_tls = use_tls
self.use_ipv6 = False
self.add_event_handler("failed_all_auth", self.disconnect_on_login_fail)
self.add_event_handler("session_start", self.start)
@@ -163,7 +164,7 @@ async def async_send_message( # noqa: C901
self.register_plugin("xep_0128") # Service Discovery
self.register_plugin("xep_0363") # HTTP upload
self.connect(force_starttls=self.force_starttls, use_ssl=False)
self.connect()
async def start(self, event):
"""Start the communication and sends the message."""

View File

@@ -16,7 +16,7 @@
},
"iot_class": "local_push",
"loggers": ["async_upnp_client", "yeelight"],
"requirements": ["yeelight==0.7.16", "async-upnp-client==0.44.0"],
"requirements": ["yeelight==0.7.16", "async-upnp-client==0.45.0"],
"zeroconf": [
{
"type": "_miio._udp.local.",

View File

@@ -21,7 +21,7 @@
"zha",
"universal_silabs_flasher"
],
"requirements": ["zha==0.0.61"],
"requirements": ["zha==0.0.62"],
"usb": [
{
"vid": "10C4",

View File

@@ -495,10 +495,23 @@ class ZWaveJSConfigFlow(ConfigFlow, domain=DOMAIN):
self._usb_discovery = True
if current_config_entries:
return await self.async_step_intent_migrate()
return await self.async_step_confirm_usb_migration()
return await self.async_step_installation_type()
async def async_step_confirm_usb_migration(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Confirm USB migration."""
if user_input is not None:
return await self.async_step_intent_migrate()
return self.async_show_form(
step_id="confirm_usb_migration",
description_placeholders={
"usb_title": self.context["title_placeholders"][CONF_NAME],
},
)
async def async_step_manual(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:

View File

@@ -5,7 +5,6 @@ from __future__ import annotations
from collections.abc import Sequence
from typing import Any
from zwave_js_server.const import NodeStatus
from zwave_js_server.exceptions import BaseZwaveJSServerError
from zwave_js_server.model.driver import Driver
from zwave_js_server.model.value import (
@@ -27,8 +26,6 @@ from .discovery import ZwaveDiscoveryInfo
from .helpers import get_device_id, get_unique_id, get_valueless_base_unique_id
EVENT_VALUE_REMOVED = "value removed"
EVENT_DEAD = "dead"
EVENT_ALIVE = "alive"
class ZWaveBaseEntity(Entity):
@@ -141,11 +138,6 @@ class ZWaveBaseEntity(Entity):
)
)
for status_event in (EVENT_ALIVE, EVENT_DEAD):
self.async_on_remove(
self.info.node.on(status_event, self._node_status_alive_or_dead)
)
self.async_on_remove(
async_dispatcher_connect(
self.hass,
@@ -211,19 +203,7 @@ class ZWaveBaseEntity(Entity):
@property
def available(self) -> bool:
"""Return entity availability."""
return (
self.driver.client.connected
and bool(self.info.node.ready)
and self.info.node.status != NodeStatus.DEAD
)
@callback
def _node_status_alive_or_dead(self, event_data: dict) -> None:
"""Call when node status changes to alive or dead.
Should not be overridden by subclasses.
"""
self.async_write_ha_state()
return self.driver.client.connected and bool(self.info.node.ready)
@callback
def _value_changed(self, event_data: dict) -> None:

View File

@@ -108,6 +108,10 @@
"start_addon": {
"title": "Configuring add-on"
},
"confirm_usb_migration": {
"description": "You are about to migrate your Z-Wave network from the old adapter to the new adapter {usb_title}. This will take a backup of the network from the old adapter and restore the network to the new adapter.\n\nPress Submit to continue with the migration.",
"title": "Migrate to a new adapter"
},
"zeroconf_confirm": {
"description": "Do you want to add the Z-Wave Server with home ID {home_id} found at {url} to Home Assistant?",
"title": "Discovered Z-Wave Server"

View File

@@ -200,18 +200,13 @@ class ZWaveNodeFirmwareUpdate(UpdateEntity):
)
return
# If device is asleep/dead, wait for it to wake up/become alive before
# attempting an update
for status, event_name in (
(NodeStatus.ASLEEP, "wake up"),
(NodeStatus.DEAD, "alive"),
):
if self.node.status == status:
if not self._status_unsub:
self._status_unsub = self.node.once(
event_name, self._update_on_status_change
)
return
# If device is asleep, wait for it to wake up before attempting an update
if self.node.status == NodeStatus.ASLEEP:
if not self._status_unsub:
self._status_unsub = self.node.once(
"wake up", self._update_on_status_change
)
return
try:
# Retrieve all firmware updates including non-stable ones but filter

View File

@@ -25,7 +25,7 @@ if TYPE_CHECKING:
APPLICATION_NAME: Final = "HomeAssistant"
MAJOR_VERSION: Final = 2025
MINOR_VERSION: Final = 7
PATCH_VERSION: Final = "0"
PATCH_VERSION: Final = "4"
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 2)

View File

@@ -6,14 +6,14 @@ aiodns==3.5.0
aiohasupervisor==0.3.1
aiohttp-asyncmdnsresolver==0.1.1
aiohttp-fast-zlib==0.3.0
aiohttp==3.12.13
aiohttp==3.12.14
aiohttp_cors==0.8.1
aiousbwatcher==1.1.1
aiozoneinfo==0.2.3
annotatedyaml==0.4.5
astral==2.2
async-interrupt==1.2.2
async-upnp-client==0.44.0
async-upnp-client==0.45.0
atomicwrites-homeassistant==1.4.1
attrs==25.3.0
audioop-lts==0.2.1
@@ -35,10 +35,10 @@ fnv-hash-fast==1.5.0
go2rtc-client==0.2.1
ha-ffmpeg==3.2.2
habluetooth==3.49.0
hass-nabucasa==0.104.0
hass-nabucasa==0.106.0
hassil==2.2.3
home-assistant-bluetooth==1.13.1
home-assistant-frontend==20250702.0
home-assistant-frontend==20250702.3
home-assistant-intents==2025.6.23
httpx==0.28.1
ifaddr==0.2.0

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "homeassistant"
version = "2025.7.0"
version = "2025.7.4"
license = "Apache-2.0"
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
description = "Open-source home automation platform running on Python 3."
@@ -28,7 +28,7 @@ dependencies = [
# change behavior based on presence of supervisor. Deprecated with #127228
# Lib can be removed with 2025.11
"aiohasupervisor==0.3.1",
"aiohttp==3.12.13",
"aiohttp==3.12.14",
"aiohttp_cors==0.8.1",
"aiohttp-fast-zlib==0.3.0",
"aiohttp-asyncmdnsresolver==0.1.1",
@@ -47,7 +47,7 @@ dependencies = [
"fnv-hash-fast==1.5.0",
# hass-nabucasa is imported by helpers which don't depend on the cloud
# integration
"hass-nabucasa==0.104.0",
"hass-nabucasa==0.106.0",
# When bumping httpx, please check the version pins of
# httpcore, anyio, and h11 in gen_requirements_all
"httpx==0.28.1",

4
requirements.txt generated
View File

@@ -5,7 +5,7 @@
# Home Assistant Core
aiodns==3.5.0
aiohasupervisor==0.3.1
aiohttp==3.12.13
aiohttp==3.12.14
aiohttp_cors==0.8.1
aiohttp-fast-zlib==0.3.0
aiohttp-asyncmdnsresolver==0.1.1
@@ -22,7 +22,7 @@ certifi>=2021.5.30
ciso8601==2.3.2
cronsim==2.6
fnv-hash-fast==1.5.0
hass-nabucasa==0.104.0
hass-nabucasa==0.106.0
httpx==0.28.1
home-assistant-bluetooth==1.13.1
ifaddr==0.2.0

58
requirements_all.txt generated
View File

@@ -84,7 +84,7 @@ PyQRCode==1.2.1
PyRMVtransport==0.3.3
# homeassistant.components.switchbot
PySwitchbot==0.67.0
PySwitchbot==0.68.2
# homeassistant.components.switchmate
PySwitchmate==0.5.1
@@ -100,7 +100,7 @@ PyTransportNSW==0.1.1
PyTurboJPEG==1.8.0
# homeassistant.components.vicare
PyViCare==2.44.0
PyViCare==2.50.0
# homeassistant.components.xiaomi_aqara
PyXiaomiGateway==0.14.3
@@ -185,7 +185,7 @@ aioairzone-cloud==0.6.12
aioairzone==1.0.0
# homeassistant.components.alexa_devices
aioamazondevices==3.2.2
aioamazondevices==3.5.1
# homeassistant.components.ambient_network
# homeassistant.components.ambient_station
@@ -283,7 +283,7 @@ aiohue==4.7.4
aioimaplib==2.0.1
# homeassistant.components.immich
aioimmich==0.10.1
aioimmich==0.10.2
# homeassistant.components.apache_kafka
aiokafka==0.10.0
@@ -381,7 +381,7 @@ aioruuvigateway==0.1.0
aiosenz==1.0.0
# homeassistant.components.shelly
aioshelly==13.7.1
aioshelly==13.7.2
# homeassistant.components.skybell
aioskybell==22.7.0
@@ -414,7 +414,7 @@ aiotedee==0.2.25
aiotractive==0.6.0
# homeassistant.components.unifi
aiounifi==83
aiounifi==84
# homeassistant.components.usb
aiousbwatcher==1.1.1
@@ -435,7 +435,7 @@ aiowatttime==0.1.1
aiowebdav2==0.4.6
# homeassistant.components.webostv
aiowebostv==0.7.3
aiowebostv==0.7.4
# homeassistant.components.withings
aiowithings==3.1.6
@@ -527,7 +527,7 @@ asmog==0.0.6
# homeassistant.components.ssdp
# homeassistant.components.upnp
# homeassistant.components.yeelight
async-upnp-client==0.44.0
async-upnp-client==0.45.0
# homeassistant.components.arve
asyncarve==0.1.1
@@ -1020,7 +1020,7 @@ georss-qld-bushfire-alert-client==0.8
getmac==0.9.5
# homeassistant.components.gios
gios==6.0.0
gios==6.1.2
# homeassistant.components.gitter
gitterpy==0.1.7
@@ -1121,13 +1121,13 @@ ha-philipsjs==3.2.2
ha-silabs-firmware-client==0.2.0
# homeassistant.components.habitica
habiticalib==0.4.0
habiticalib==0.4.1
# homeassistant.components.bluetooth
habluetooth==3.49.0
# homeassistant.components.cloud
hass-nabucasa==0.104.0
hass-nabucasa==0.106.0
# homeassistant.components.splunk
hass-splunk==0.1.1
@@ -1168,13 +1168,13 @@ hole==0.8.0
holidays==0.75
# homeassistant.components.frontend
home-assistant-frontend==20250702.0
home-assistant-frontend==20250702.3
# homeassistant.components.conversation
home-assistant-intents==2025.6.23
# homeassistant.components.homematicip_cloud
homematicip==2.0.6
homematicip==2.0.7
# homeassistant.components.horizon
horimote==0.4.1
@@ -1452,7 +1452,7 @@ monzopy==1.4.2
mopeka-iot-ble==0.8.0
# homeassistant.components.motion_blinds
motionblinds==0.6.28
motionblinds==0.6.29
# homeassistant.components.motionblinds_ble
motionblindsble==0.1.3
@@ -1467,7 +1467,7 @@ mozart-api==4.1.1.116.4
mullvad-api==1.0.0
# homeassistant.components.music_assistant
music-assistant-client==1.2.3
music-assistant-client==1.2.4
# homeassistant.components.tts
mutagen==1.47.0
@@ -1555,7 +1555,7 @@ numato-gpio==0.13.0
numpy==2.3.0
# homeassistant.components.nyt_games
nyt_games==0.4.4
nyt_games==0.5.0
# homeassistant.components.oasa_telematics
oasatelematics==0.3
@@ -1962,7 +1962,7 @@ pyeiscp==0.0.7
pyemoncms==0.1.1
# homeassistant.components.enphase_envoy
pyenphase==2.1.0
pyenphase==2.2.2
# homeassistant.components.envisalink
pyenvisalink==4.7
@@ -2100,7 +2100,7 @@ pykwb==0.0.8
pylacrosse==0.4
# homeassistant.components.lamarzocco
pylamarzocco==2.0.9
pylamarzocco==2.0.11
# homeassistant.components.lastfm
pylast==5.1.0
@@ -2309,7 +2309,7 @@ pysabnzbd==1.1.1
pysaj==0.0.16
# homeassistant.components.schlage
pyschlage==2025.4.0
pyschlage==2025.7.2
# homeassistant.components.sensibo
pysensibo==1.2.1
@@ -2348,7 +2348,7 @@ pysmappee==0.2.29
pysmarlaapi==0.9.0
# homeassistant.components.smartthings
pysmartthings==3.2.5
pysmartthings==3.2.8
# homeassistant.components.smarty
pysmarty2==0.10.2
@@ -2360,7 +2360,7 @@ pysmhi==1.0.2
pysml==0.1.5
# homeassistant.components.smlight
pysmlight==0.2.6
pysmlight==0.2.7
# homeassistant.components.snmp
pysnmp==6.2.6
@@ -2384,7 +2384,7 @@ pysqueezebox==0.12.1
pystiebeleltron==0.1.0
# homeassistant.components.suez_water
pysuezV2==2.0.5
pysuezV2==2.0.7
# homeassistant.components.switchbee
pyswitchbee==1.8.3
@@ -2596,7 +2596,7 @@ pywilight==0.0.74
pywizlight==0.6.3
# homeassistant.components.wmspro
pywmspro==0.3.0
pywmspro==0.3.2
# homeassistant.components.ws66i
pyws66i==1.1
@@ -2756,7 +2756,7 @@ sentry-sdk==1.45.1
sfrbox-api==0.0.11
# homeassistant.components.sharkiq
sharkiq==1.1.0
sharkiq==1.1.1
# homeassistant.components.aquostv
sharp_aquos_rc==0.3.2
@@ -2786,7 +2786,7 @@ skyboxremote==0.0.6
slack_sdk==3.33.4
# homeassistant.components.xmpp
slixmpp==1.8.5
slixmpp==1.10.0
# homeassistant.components.smart_meter_texas
smart-meter-texas==0.5.5
@@ -2904,7 +2904,7 @@ temperusb==1.6.1
# homeassistant.components.tesla_fleet
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==1.2.0
tesla-fleet-api==1.2.2
# homeassistant.components.powerwall
tesla-powerwall==0.5.2
@@ -2994,7 +2994,7 @@ typedmonarchmoney==0.4.4
uasiren==0.0.1
# homeassistant.components.unifiprotect
uiprotect==7.14.1
uiprotect==7.14.2
# homeassistant.components.landisgyr_heat_meter
ultraheat-api==0.5.7
@@ -3041,7 +3041,7 @@ vehicle==2.2.2
velbus-aio==2025.5.0
# homeassistant.components.venstar
venstarcolortouch==0.19
venstarcolortouch==0.21
# homeassistant.components.vilfo
vilfo-api-client==0.5.0
@@ -3190,7 +3190,7 @@ zeroconf==0.147.0
zeversolar==0.3.2
# homeassistant.components.zha
zha==0.0.61
zha==0.0.62
# homeassistant.components.zhong_hong
zhong-hong-hvac==1.0.13

View File

@@ -81,7 +81,7 @@ PyQRCode==1.2.1
PyRMVtransport==0.3.3
# homeassistant.components.switchbot
PySwitchbot==0.67.0
PySwitchbot==0.68.2
# homeassistant.components.syncthru
PySyncThru==0.8.0
@@ -94,7 +94,7 @@ PyTransportNSW==0.1.1
PyTurboJPEG==1.8.0
# homeassistant.components.vicare
PyViCare==2.44.0
PyViCare==2.50.0
# homeassistant.components.xiaomi_aqara
PyXiaomiGateway==0.14.3
@@ -173,7 +173,7 @@ aioairzone-cloud==0.6.12
aioairzone==1.0.0
# homeassistant.components.alexa_devices
aioamazondevices==3.2.2
aioamazondevices==3.5.1
# homeassistant.components.ambient_network
# homeassistant.components.ambient_station
@@ -268,7 +268,7 @@ aiohue==4.7.4
aioimaplib==2.0.1
# homeassistant.components.immich
aioimmich==0.10.1
aioimmich==0.10.2
# homeassistant.components.apache_kafka
aiokafka==0.10.0
@@ -363,7 +363,7 @@ aioruuvigateway==0.1.0
aiosenz==1.0.0
# homeassistant.components.shelly
aioshelly==13.7.1
aioshelly==13.7.2
# homeassistant.components.skybell
aioskybell==22.7.0
@@ -396,7 +396,7 @@ aiotedee==0.2.25
aiotractive==0.6.0
# homeassistant.components.unifi
aiounifi==83
aiounifi==84
# homeassistant.components.usb
aiousbwatcher==1.1.1
@@ -417,7 +417,7 @@ aiowatttime==0.1.1
aiowebdav2==0.4.6
# homeassistant.components.webostv
aiowebostv==0.7.3
aiowebostv==0.7.4
# homeassistant.components.withings
aiowithings==3.1.6
@@ -491,7 +491,7 @@ arcam-fmj==1.8.1
# homeassistant.components.ssdp
# homeassistant.components.upnp
# homeassistant.components.yeelight
async-upnp-client==0.44.0
async-upnp-client==0.45.0
# homeassistant.components.arve
asyncarve==0.1.1
@@ -890,7 +890,7 @@ georss-qld-bushfire-alert-client==0.8
getmac==0.9.5
# homeassistant.components.gios
gios==6.0.0
gios==6.1.2
# homeassistant.components.glances
glances-api==0.8.0
@@ -982,13 +982,13 @@ ha-philipsjs==3.2.2
ha-silabs-firmware-client==0.2.0
# homeassistant.components.habitica
habiticalib==0.4.0
habiticalib==0.4.1
# homeassistant.components.bluetooth
habluetooth==3.49.0
# homeassistant.components.cloud
hass-nabucasa==0.104.0
hass-nabucasa==0.106.0
# homeassistant.components.assist_satellite
# homeassistant.components.conversation
@@ -1017,13 +1017,13 @@ hole==0.8.0
holidays==0.75
# homeassistant.components.frontend
home-assistant-frontend==20250702.0
home-assistant-frontend==20250702.3
# homeassistant.components.conversation
home-assistant-intents==2025.6.23
# homeassistant.components.homematicip_cloud
homematicip==2.0.6
homematicip==2.0.7
# homeassistant.components.remember_the_milk
httplib2==0.20.4
@@ -1244,7 +1244,7 @@ monzopy==1.4.2
mopeka-iot-ble==0.8.0
# homeassistant.components.motion_blinds
motionblinds==0.6.28
motionblinds==0.6.29
# homeassistant.components.motionblinds_ble
motionblindsble==0.1.3
@@ -1259,7 +1259,7 @@ mozart-api==4.1.1.116.4
mullvad-api==1.0.0
# homeassistant.components.music_assistant
music-assistant-client==1.2.3
music-assistant-client==1.2.4
# homeassistant.components.tts
mutagen==1.47.0
@@ -1329,7 +1329,7 @@ numato-gpio==0.13.0
numpy==2.3.0
# homeassistant.components.nyt_games
nyt_games==0.4.4
nyt_games==0.5.0
# homeassistant.components.google
oauth2client==4.1.3
@@ -1637,7 +1637,7 @@ pyeiscp==0.0.7
pyemoncms==0.1.1
# homeassistant.components.enphase_envoy
pyenphase==2.1.0
pyenphase==2.2.2
# homeassistant.components.everlights
pyeverlights==0.1.0
@@ -1745,7 +1745,7 @@ pykrakenapi==0.1.8
pykulersky==0.5.8
# homeassistant.components.lamarzocco
pylamarzocco==2.0.9
pylamarzocco==2.0.11
# homeassistant.components.lastfm
pylast==5.1.0
@@ -1921,7 +1921,7 @@ pyrympro==0.0.9
pysabnzbd==1.1.1
# homeassistant.components.schlage
pyschlage==2025.4.0
pyschlage==2025.7.2
# homeassistant.components.sensibo
pysensibo==1.2.1
@@ -1951,7 +1951,7 @@ pysmappee==0.2.29
pysmarlaapi==0.9.0
# homeassistant.components.smartthings
pysmartthings==3.2.5
pysmartthings==3.2.8
# homeassistant.components.smarty
pysmarty2==0.10.2
@@ -1963,7 +1963,7 @@ pysmhi==1.0.2
pysml==0.1.5
# homeassistant.components.smlight
pysmlight==0.2.6
pysmlight==0.2.7
# homeassistant.components.snmp
pysnmp==6.2.6
@@ -1987,7 +1987,7 @@ pysqueezebox==0.12.1
pystiebeleltron==0.1.0
# homeassistant.components.suez_water
pysuezV2==2.0.5
pysuezV2==2.0.7
# homeassistant.components.switchbee
pyswitchbee==1.8.3
@@ -2154,7 +2154,7 @@ pywilight==0.0.74
pywizlight==0.6.3
# homeassistant.components.wmspro
pywmspro==0.3.0
pywmspro==0.3.2
# homeassistant.components.ws66i
pyws66i==1.1
@@ -2278,7 +2278,7 @@ sentry-sdk==1.45.1
sfrbox-api==0.0.11
# homeassistant.components.sharkiq
sharkiq==1.1.0
sharkiq==1.1.1
# homeassistant.components.simplefin
simplefin4py==0.0.18
@@ -2390,7 +2390,7 @@ temperusb==1.6.1
# homeassistant.components.tesla_fleet
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==1.2.0
tesla-fleet-api==1.2.2
# homeassistant.components.powerwall
tesla-powerwall==0.5.2
@@ -2468,7 +2468,7 @@ typedmonarchmoney==0.4.4
uasiren==0.0.1
# homeassistant.components.unifiprotect
uiprotect==7.14.1
uiprotect==7.14.2
# homeassistant.components.landisgyr_heat_meter
ultraheat-api==0.5.7
@@ -2509,7 +2509,7 @@ vehicle==2.2.2
velbus-aio==2025.5.0
# homeassistant.components.venstar
venstarcolortouch==0.19
venstarcolortouch==0.21
# homeassistant.components.vilfo
vilfo-api-client==0.5.0
@@ -2634,7 +2634,7 @@ zeroconf==0.147.0
zeversolar==0.3.2
# homeassistant.components.zha
zha==0.0.61
zha==0.0.62
# homeassistant.components.zwave_js
zwave-js-server-python==0.65.0

Some files were not shown because too many files have changed in this diff Show More