Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
2afe475
Add more mac address prefixes for discovery to PlayStation Network (#…
tr4nt0r Jul 1, 2025
9719d2e
Start deprecation of battery properties in vacuum (#146401)
gjohansson-ST Jul 1, 2025
ddf56f0
Support device removal in CoolMasterNet integration (#147851)
OnFreund Jul 1, 2025
4f7348b
Fix invalid configuration of MQTT device QoS option in subentry flow …
jbouwh Jul 1, 2025
a180cab
Use (new) common state "Full" in `overkiz` (#147848)
NoRi2909 Jul 1, 2025
35f0505
Use (new) common state "Empty" in `whirlpool` (#147847)
NoRi2909 Jul 1, 2025
9469c6a
Implement suggested_display_precision for ESPHome (#147849)
jesserockz Jul 1, 2025
5ff698c
Catch access denied errors in webdav and display proper message (#147…
jpbede Jul 1, 2025
8fc3128
Correct ollama config entry migration (#147858)
emontnemery Jul 1, 2025
99f7a03
Correct Google generative AI config entry migration (#147856)
emontnemery Jul 1, 2025
b799975
Correct anthropic config entry migration (#147857)
emontnemery Jul 1, 2025
7021fe7
Correct openai conversation config entry migration (#147859)
emontnemery Jul 1, 2025
573325b
Use correctly formatted MAC in home_connect tests (#147818)
epenet Jul 1, 2025
2e12db0
Fix wrong state in Husqvarna Automower (#146075)
Thomas55555 Jul 1, 2025
12aef4a
Use correctly formatted MAC in knocki tests (#147821)
epenet Jul 1, 2025
3f95cb3
Use correctly formatted MAC in sma tests (#147866)
epenet Jul 1, 2025
78aeae5
Use correctly formatted MAC in roomba tests (#147865)
epenet Jul 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions homeassistant/components/anthropic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,34 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
title=DEFAULT_CONVERSATION_NAME,
options={},
version=2,
minor_version=2,
)


async def async_migrate_entry(hass: HomeAssistant, entry: AnthropicConfigEntry) -> bool:
"""Migrate entry."""
LOGGER.debug("Migrating from version %s:%s", entry.version, entry.minor_version)

if entry.version > 2:
# This means the user has downgraded from a future version
return False

if entry.version == 2 and entry.minor_version == 1:
# Correct broken device migration in Home Assistant Core 2025.7.0b0-2025.7.0b1
device_registry = dr.async_get(hass)
for device in dr.async_entries_for_config_entry(
device_registry, entry.entry_id
):
device_registry.async_update_device(
device.id,
remove_config_entry_id=entry.entry_id,
remove_config_subentry_id=None,
)

hass.config_entries.async_update_entry(entry, minor_version=2)

LOGGER.debug(
"Migration to version %s:%s successful", entry.version, entry.minor_version
)

return True
1 change: 1 addition & 0 deletions homeassistant/components/anthropic/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class AnthropicConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Anthropic."""

VERSION = 2
MINOR_VERSION = 2

async def async_step_user(
self, user_input: dict[str, Any] | None = None
Expand Down
14 changes: 13 additions & 1 deletion homeassistant/components/coolmaster/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr

from .const import CONF_SWING_SUPPORT
from .const import CONF_SWING_SUPPORT, DOMAIN
from .coordinator import CoolmasterConfigEntry, CoolmasterDataUpdateCoordinator

PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.CLIMATE, Platform.SENSOR]
Expand Down Expand Up @@ -48,3 +49,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: CoolmasterConfigEntry) -
async def async_unload_entry(hass: HomeAssistant, entry: CoolmasterConfigEntry) -> bool:
"""Unload a Coolmaster config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


async def async_remove_config_entry_device(
hass: HomeAssistant,
config_entry: CoolmasterConfigEntry,
device_entry: dr.DeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
return not device_entry.identifiers.intersection(
(DOMAIN, unit_id) for unit_id in config_entry.runtime_data.data
)
5 changes: 3 additions & 2 deletions homeassistant/components/esphome/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def _on_static_info_update(self, static_info: EntityInfo) -> None:
# if the string is empty
if unit_of_measurement := static_info.unit_of_measurement:
self._attr_native_unit_of_measurement = unit_of_measurement
self._attr_suggested_display_precision = static_info.accuracy_decimals
self._attr_device_class = try_parse_enum(
SensorDeviceClass, static_info.device_class
)
Expand All @@ -97,7 +98,7 @@ def _on_static_info_update(self, static_info: EntityInfo) -> None:
self._attr_state_class = _STATE_CLASSES.from_esphome(state_class)

@property
def native_value(self) -> datetime | str | None:
def native_value(self) -> datetime | int | float | None:
"""Return the state of the entity."""
if not self._has_state or (state := self._state).missing_state:
return None
Expand All @@ -106,7 +107,7 @@ def native_value(self) -> datetime | str | None:
return None
if self.device_class is SensorDeviceClass.TIMESTAMP:
return dt_util.utc_from_timestamp(state_float)
return f"{state_float:.{self._static_info.accuracy_decimals}f}"
return state_float


class EsphomeTextSensor(EsphomeEntity[TextSensorInfo, TextSensorState], SensorEntity):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,50 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
title=DEFAULT_TITLE,
options={},
version=2,
minor_version=2,
)


async def async_migrate_entry(
hass: HomeAssistant, entry: GoogleGenerativeAIConfigEntry
) -> bool:
"""Migrate entry."""
LOGGER.debug("Migrating from version %s:%s", entry.version, entry.minor_version)

if entry.version > 2:
# This means the user has downgraded from a future version
return False

if entry.version == 2 and entry.minor_version == 1:
# Add TTS subentry which was missing in 2025.7.0b0
if not any(
subentry.subentry_type == "tts" for subentry in entry.subentries.values()
):
hass.config_entries.async_add_subentry(
entry,
ConfigSubentry(
data=MappingProxyType(RECOMMENDED_TTS_OPTIONS),
subentry_type="tts",
title=DEFAULT_TTS_NAME,
unique_id=None,
),
)

# Correct broken device migration in Home Assistant Core 2025.7.0b0-2025.7.0b1
device_registry = dr.async_get(hass)
for device in dr.async_entries_for_config_entry(
device_registry, entry.entry_id
):
device_registry.async_update_device(
device.id,
remove_config_entry_id=entry.entry_id,
remove_config_subentry_id=None,
)

hass.config_entries.async_update_entry(entry, minor_version=2)

LOGGER.debug(
"Migration to version %s:%s successful", entry.version, entry.minor_version
)

return True
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class GoogleGenerativeAIConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Google Generative AI Conversation."""

VERSION = 2
MINOR_VERSION = 2

async def async_step_api(
self, user_input: dict[str, Any] | None = None
Expand Down
12 changes: 12 additions & 0 deletions homeassistant/components/husqvarna_automower/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
"""The constants for the Husqvarna Automower integration."""

from aioautomower.model import MowerStates

DOMAIN = "husqvarna_automower"
EXECUTION_TIME_DELAY = 5
NAME = "Husqvarna Automower"
OAUTH2_AUTHORIZE = "https://api.authentication.husqvarnagroup.dev/v1/oauth2/authorize"
OAUTH2_TOKEN = "https://api.authentication.husqvarnagroup.dev/v1/oauth2/token"

ERROR_STATES = [
MowerStates.ERROR_AT_POWER_UP,
MowerStates.ERROR,
MowerStates.FATAL_ERROR,
MowerStates.OFF,
MowerStates.STOPPED,
MowerStates.WAIT_POWER_UP,
MowerStates.WAIT_UPDATING,
]
20 changes: 15 additions & 5 deletions homeassistant/components/husqvarna_automower/lawn_mower.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from . import AutomowerConfigEntry
from .const import DOMAIN
from .const import DOMAIN, ERROR_STATES
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import AutomowerAvailableEntity, handle_sending_exception

Expand Down Expand Up @@ -108,18 +108,28 @@ def __init__(
def activity(self) -> LawnMowerActivity:
"""Return the state of the mower."""
mower_attributes = self.mower_attributes
if mower_attributes.mower.state in ERROR_STATES:
return LawnMowerActivity.ERROR
if mower_attributes.mower.state in PAUSED_STATES:
return LawnMowerActivity.PAUSED
if (mower_attributes.mower.state == "RESTRICTED") or (
mower_attributes.mower.activity in DOCKED_ACTIVITIES
if mower_attributes.mower.activity == MowerActivities.GOING_HOME:
return LawnMowerActivity.RETURNING
if (
mower_attributes.mower.state is MowerStates.RESTRICTED
or mower_attributes.mower.activity in DOCKED_ACTIVITIES
):
return LawnMowerActivity.DOCKED
if mower_attributes.mower.state in MowerStates.IN_OPERATION:
if mower_attributes.mower.activity == MowerActivities.GOING_HOME:
return LawnMowerActivity.RETURNING
return LawnMowerActivity.MOWING
return LawnMowerActivity.ERROR

@property
def available(self) -> bool:
"""Return the available attribute of the entity."""
return (
super().available and self.mower_attributes.mower.state != MowerStates.OFF
)

@property
def work_areas(self) -> dict[int, WorkArea] | None:
"""Return the work areas of the mower."""
Expand Down
18 changes: 2 additions & 16 deletions homeassistant/components/husqvarna_automower/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@
from operator import attrgetter
from typing import TYPE_CHECKING, Any

from aioautomower.model import (
MowerAttributes,
MowerModes,
MowerStates,
RestrictedReasons,
WorkArea,
)
from aioautomower.model import MowerAttributes, MowerModes, RestrictedReasons, WorkArea

from homeassistant.components.sensor import (
SensorDeviceClass,
Expand All @@ -27,6 +21,7 @@
from homeassistant.helpers.typing import StateType

from . import AutomowerConfigEntry
from .const import ERROR_STATES
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import (
AutomowerBaseEntity,
Expand Down Expand Up @@ -166,15 +161,6 @@
"zone_generator_problem",
]

ERROR_STATES = [
MowerStates.ERROR_AT_POWER_UP,
MowerStates.ERROR,
MowerStates.FATAL_ERROR,
MowerStates.OFF,
MowerStates.STOPPED,
MowerStates.WAIT_POWER_UP,
MowerStates.WAIT_UPDATING,
]

ERROR_KEY_LIST = list(
dict.fromkeys(ERROR_KEYS + [state.lower() for state in ERROR_STATES])
Expand Down
9 changes: 4 additions & 5 deletions homeassistant/components/mqtt/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2771,11 +2771,10 @@ async def async_step_device(
reconfig=True,
)
if user_input is not None:
new_device_data, errors = validate_user_input(
user_input, MQTT_DEVICE_PLATFORM_FIELDS
)
if "mqtt_settings" in user_input:
new_device_data["mqtt_settings"] = user_input["mqtt_settings"]
new_device_data: dict[str, Any] = user_input.copy()
_, errors = validate_user_input(user_input, MQTT_DEVICE_PLATFORM_FIELDS)
if "advanced_settings" in new_device_data:
new_device_data |= new_device_data.pop("advanced_settings")
if not errors:
self._subentry_data[CONF_DEVICE] = cast(MqttDeviceData, new_device_data)
if self.source == SOURCE_RECONFIGURE:
Expand Down
30 changes: 30 additions & 0 deletions homeassistant/components/ollama/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,34 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
title=DEFAULT_NAME,
options={},
version=2,
minor_version=2,
)


async def async_migrate_entry(hass: HomeAssistant, entry: OllamaConfigEntry) -> bool:
"""Migrate entry."""
_LOGGER.debug("Migrating from version %s:%s", entry.version, entry.minor_version)

if entry.version > 2:
# This means the user has downgraded from a future version
return False

if entry.version == 2 and entry.minor_version == 1:
# Correct broken device migration in Home Assistant Core 2025.7.0b0-2025.7.0b1
device_registry = dr.async_get(hass)
for device in dr.async_entries_for_config_entry(
device_registry, entry.entry_id
):
device_registry.async_update_device(
device.id,
remove_config_entry_id=entry.entry_id,
remove_config_subentry_id=None,
)

hass.config_entries.async_update_entry(entry, minor_version=2)

_LOGGER.debug(
"Migration to version %s:%s successful", entry.version, entry.minor_version
)

return True
1 change: 1 addition & 0 deletions homeassistant/components/ollama/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class OllamaConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Ollama."""

VERSION = 2
MINOR_VERSION = 2

def __init__(self) -> None:
"""Initialize config flow."""
Expand Down
30 changes: 30 additions & 0 deletions homeassistant/components/openai_conversation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,34 @@ async def async_migrate_integration(hass: HomeAssistant) -> None:
title=DEFAULT_NAME,
options={},
version=2,
minor_version=2,
)


async def async_migrate_entry(hass: HomeAssistant, entry: OpenAIConfigEntry) -> bool:
"""Migrate entry."""
LOGGER.debug("Migrating from version %s:%s", entry.version, entry.minor_version)

if entry.version > 2:
# This means the user has downgraded from a future version
return False

if entry.version == 2 and entry.minor_version == 1:
# Correct broken device migration in Home Assistant Core 2025.7.0b0-2025.7.0b1
device_registry = dr.async_get(hass)
for device in dr.async_entries_for_config_entry(
device_registry, entry.entry_id
):
device_registry.async_update_device(
device.id,
remove_config_entry_id=entry.entry_id,
remove_config_subentry_id=None,
)

hass.config_entries.async_update_entry(entry, minor_version=2)

LOGGER.debug(
"Migration to version %s:%s successful", entry.version, entry.minor_version
)

return True
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class OpenAIConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for OpenAI Conversation."""

VERSION = 2
MINOR_VERSION = 2

async def async_step_user(
self, user_input: dict[str, Any] | None = None
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/overkiz/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"sensor": {
"battery": {
"state": {
"full": "Full",
"full": "[%key:common::state::full%]",
"low": "[%key:common::state::low%]",
"normal": "[%key:common::state::normal%]",
"medium": "[%key:common::state::medium%]",
Expand Down
15 changes: 15 additions & 0 deletions homeassistant/components/playstation_network/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,21 @@
},
{
"macaddress": "D44B5E*"
},
{
"macaddress": "F8D0AC*"
},
{
"macaddress": "E86E3A*"
},
{
"macaddress": "FC0FE6*"
},
{
"macaddress": "9C37CB*"
},
{
"macaddress": "84E657*"
}
],
"documentation": "https://www.home-assistant.io/integrations/playstation_network",
Expand Down
Loading
Loading