Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bba7f5c
Z-WaveJS config flow: Change keys question (#147518)
MindFreeze Jun 27, 2025
a1518b9
Update frontend to 20250627.0 (#147668)
piitaya Jun 27, 2025
8ee5c30
Update ruff to 0.12.1 (#147677)
cdce8p Jun 27, 2025
2120ff6
Fix Shelly entity removal (#147665)
thecode Jun 27, 2025
113e7dc
Add data descriptions to PEGELONLINE integration (#147594)
mib1185 Jun 27, 2025
ff71132
Add codeowner for Telegram bot (#147680)
hanwg Jun 27, 2025
4cab3a0
Bump aioamazondevices to 3.1.22 (#147681)
chemelli74 Jun 27, 2025
b8500b3
Improve tests for binary sensor template (#147657)
epenet Jun 27, 2025
0be0e22
Simplify rflink dimmable set_level parsing (#147636)
scop Jun 27, 2025
5129f89
Finish config flow in huawei_lte SSDP test (#147542)
scop Jun 27, 2025
b630fb0
Respect availability of parent class in Husqvarna Automower (#147649)
Thomas55555 Jun 27, 2025
e3ba1f3
Matter TemperatureControl (#145706)
lboue Jun 27, 2025
19d89c8
Fix energy history in Teslemetry (#147646)
Bre77 Jun 27, 2025
d874c28
Add previously missing state classes to dsmr sensors (#147633)
bajansen Jun 27, 2025
18c1953
Add lock models to switchbot cloud (#147569)
XiaoLing-git Jun 27, 2025
32236b2
Add reconfiguration flow to PlayStation Network (#147552)
tr4nt0r Jun 27, 2025
571376b
Bump aioautomower to 1.0.1 (#147683)
Thomas55555 Jun 27, 2025
1d82d44
Add device prefix to summary in Husqvarna Automower (#147405)
Thomas55555 Jun 27, 2025
91c3b43
Improve comment for helpers.entity.entity_sources (#146529)
emontnemery Jun 27, 2025
ea6332e
Move backup services to separate module (#146427)
epenet Jun 27, 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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.0
rev: v0.12.1
hooks:
- id: ruff-check
args:
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions homeassistant/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ async def async_enable_logging(
)
threading.excepthook = lambda args: logging.getLogger().exception(
"Uncaught thread exception",
exc_info=( # type: ignore[arg-type] # noqa: LOG014
exc_info=( # type: ignore[arg-type]
args.exc_type,
args.exc_value,
args.exc_traceback,
Expand Down Expand Up @@ -1061,5 +1061,5 @@ async def _async_setup_multi_components(
_LOGGER.error(
"Error setting up integration %s - received exception",
domain,
exc_info=(type(result), result, result.__traceback__), # noqa: LOG014
exc_info=(type(result), result, result.__traceback__),
)
2 changes: 1 addition & 1 deletion homeassistant/components/alexa_devices/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "bronze",
"requirements": ["aioamazondevices==3.1.19"]
"requirements": ["aioamazondevices==3.1.22"]
}
27 changes: 3 additions & 24 deletions homeassistant/components/backup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from homeassistant.config_entries import SOURCE_SYSTEM
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, discovery_flow
from homeassistant.helpers.backup import DATA_BACKUP
from homeassistant.helpers.hassio import is_hassio
Expand Down Expand Up @@ -45,6 +45,7 @@
WrittenBackup,
)
from .models import AddonInfo, AgentBackup, BackupNotFound, Folder
from .services import async_setup_services
from .util import suggested_filename, suggested_filename_from_name_date
from .websocket import async_register_websocket_handlers

Expand Down Expand Up @@ -113,29 +114,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:

async_register_websocket_handlers(hass, with_hassio)

async def async_handle_create_service(call: ServiceCall) -> None:
"""Service handler for creating backups."""
agent_id = list(backup_manager.local_backup_agents)[0]
await backup_manager.async_create_backup(
agent_ids=[agent_id],
include_addons=None,
include_all_addons=False,
include_database=True,
include_folders=None,
include_homeassistant=True,
name=None,
password=None,
)

async def async_handle_create_automatic_service(call: ServiceCall) -> None:
"""Service handler for creating automatic backups."""
await backup_manager.async_create_automatic_backup()

if not with_hassio:
hass.services.async_register(DOMAIN, "create", async_handle_create_service)
hass.services.async_register(
DOMAIN, "create_automatic", async_handle_create_automatic_service
)
async_setup_services(hass)

async_register_http_views(hass)

Expand Down
36 changes: 36 additions & 0 deletions homeassistant/components/backup/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""The Backup integration."""

from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.hassio import is_hassio

from .const import DATA_MANAGER, DOMAIN


async def _async_handle_create_service(call: ServiceCall) -> None:
"""Service handler for creating backups."""
backup_manager = call.hass.data[DATA_MANAGER]
agent_id = list(backup_manager.local_backup_agents)[0]
await backup_manager.async_create_backup(
agent_ids=[agent_id],
include_addons=None,
include_all_addons=False,
include_database=True,
include_folders=None,
include_homeassistant=True,
name=None,
password=None,
)


async def _async_handle_create_automatic_service(call: ServiceCall) -> None:
"""Service handler for creating automatic backups."""
await call.hass.data[DATA_MANAGER].async_create_automatic_backup()


def async_setup_services(hass: HomeAssistant) -> None:
"""Register services."""
if not is_hassio(hass):
hass.services.async_register(DOMAIN, "create", _async_handle_create_service)
hass.services.async_register(
DOMAIN, "create_automatic", _async_handle_create_automatic_service
)
8 changes: 8 additions & 0 deletions homeassistant/components/dsmr/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ class MbusDeviceType(IntEnum):
obis_reference="SHORT_POWER_FAILURE_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -249,6 +250,7 @@ class MbusDeviceType(IntEnum):
obis_reference="LONG_POWER_FAILURE_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -257,6 +259,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SAG_L1_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -265,6 +268,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SAG_L2_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -273,6 +277,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SAG_L3_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -281,6 +286,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SWELL_L1_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -289,6 +295,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SWELL_L2_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand All @@ -297,6 +304,7 @@ class MbusDeviceType(IntEnum):
obis_reference="VOLTAGE_SWELL_L3_COUNT",
dsmr_versions={"2.2", "4", "5", "5L"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20250626.0"]
"requirements": ["home-assistant-frontend==20250627.0"]
}
4 changes: 3 additions & 1 deletion homeassistant/components/husqvarna_automower/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def __init__(
@property
def available(self) -> bool:
"""Return the available attribute of the entity."""
return self.entity_description.available_fn(self.mower_attributes)
return super().available and self.entity_description.available_fn(
self.mower_attributes
)

@handle_sending_exception()
async def async_press(self) -> None:
Expand Down
20 changes: 18 additions & 2 deletions homeassistant/components/husqvarna_automower/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

from datetime import datetime
import logging
from typing import TYPE_CHECKING

from aioautomower.model import make_name_string

from homeassistant.components.calendar import CalendarEntity, CalendarEvent
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.util import dt as dt_util

from . import AutomowerConfigEntry
from .const import DOMAIN
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import AutomowerBaseEntity

Expand Down Expand Up @@ -51,6 +54,19 @@ def __init__(
self._attr_unique_id = mower_id
self._event: CalendarEvent | None = None

@property
def device_name(self) -> str:
"""Return the prefix for the event summary."""
device_registry = dr.async_get(self.hass)
device_entry = device_registry.async_get_device(
identifiers={(DOMAIN, self.mower_id)}
)
if TYPE_CHECKING:
assert device_entry is not None
assert device_entry.name is not None

return device_entry.name_by_user or device_entry.name

@property
def event(self) -> CalendarEvent | None:
"""Return the current or next upcoming event."""
Expand All @@ -66,7 +82,7 @@ def event(self) -> CalendarEvent | None:
program_event.work_area_id
]
return CalendarEvent(
summary=make_name_string(work_area_name, program_event.schedule_no),
summary=f"{self.device_name} {make_name_string(work_area_name, program_event.schedule_no)}",
start=program_event.start,
end=program_event.end,
rrule=program_event.rrule_str,
Expand All @@ -93,7 +109,7 @@ async def async_get_events(
]
calendar_events.append(
CalendarEvent(
summary=make_name_string(work_area_name, program_event.schedule_no),
summary=f"{self.device_name} {make_name_string(work_area_name, program_event.schedule_no)}",
start=program_event.start.replace(tzinfo=start_date.tzinfo),
end=program_event.end.replace(tzinfo=start_date.tzinfo),
rrule=program_event.rrule_str,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/husqvarna_automower/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_push",
"loggers": ["aioautomower"],
"quality_scale": "silver",
"requirements": ["aioautomower==1.0.0"]
"requirements": ["aioautomower==1.0.1"]
}
79 changes: 79 additions & 0 deletions homeassistant/components/matter/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any, cast

from chip.clusters import Objects as clusters
from chip.clusters.ClusterObjects import ClusterAttributeDescriptor, ClusterCommand
from matter_server.common import custom_clusters

from homeassistant.components.number import (
Expand Down Expand Up @@ -44,6 +47,23 @@ class MatterNumberEntityDescription(NumberEntityDescription, MatterEntityDescrip
"""Describe Matter Number Input entities."""


@dataclass(frozen=True, kw_only=True)
class MatterRangeNumberEntityDescription(
NumberEntityDescription, MatterEntityDescription
):
"""Describe Matter Number Input entities with min and max values."""

ha_to_native_value: Callable[[Any], Any]

# attribute descriptors to get the min and max value
min_attribute: type[ClusterAttributeDescriptor]
max_attribute: type[ClusterAttributeDescriptor]

# command: a custom callback to create the command to send to the device
# the callback's argument will be the index of the selected list value
command: Callable[[int], ClusterCommand]


class MatterNumber(MatterEntity, NumberEntity):
"""Representation of a Matter Attribute as a Number entity."""

Expand All @@ -67,6 +87,42 @@ def _update_from_device(self) -> None:
self._attr_native_value = value


class MatterRangeNumber(MatterEntity, NumberEntity):
"""Representation of a Matter Attribute as a Number entity with min and max values."""

entity_description: MatterRangeNumberEntityDescription

async def async_set_native_value(self, value: float) -> None:
"""Update the current value."""
send_value = self.entity_description.ha_to_native_value(value)
# custom command defined to set the new value
await self.send_device_command(
self.entity_description.command(send_value),
)

@callback
def _update_from_device(self) -> None:
"""Update from device."""
value = self.get_matter_attribute_value(self._entity_info.primary_attribute)
if value_convert := self.entity_description.measurement_to_ha:
value = value_convert(value)
self._attr_native_value = value
self._attr_native_min_value = (
cast(
int,
self.get_matter_attribute_value(self.entity_description.min_attribute),
)
/ 100
)
self._attr_native_max_value = (
cast(
int,
self.get_matter_attribute_value(self.entity_description.max_attribute),
)
/ 100
)


# Discovery schema(s) to map Matter Attributes to HA entities
DISCOVERY_SCHEMAS = [
MatterDiscoverySchema(
Expand Down Expand Up @@ -213,4 +269,27 @@ def _update_from_device(self) -> None:
entity_class=MatterNumber,
required_attributes=(clusters.DoorLock.Attributes.AutoRelockTime,),
),
MatterDiscoverySchema(
platform=Platform.NUMBER,
entity_description=MatterRangeNumberEntityDescription(
key="TemperatureControlTemperatureSetpoint",
name=None,
translation_key="temperature_setpoint",
command=lambda value: clusters.TemperatureControl.Commands.SetTemperature(
targetTemperature=value
),
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
measurement_to_ha=lambda x: None if x is None else x / 100,
ha_to_native_value=lambda x: round(x * 100),
min_attribute=clusters.TemperatureControl.Attributes.MinTemperature,
max_attribute=clusters.TemperatureControl.Attributes.MaxTemperature,
mode=NumberMode.SLIDER,
),
entity_class=MatterRangeNumber,
required_attributes=(
clusters.TemperatureControl.Attributes.TemperatureSetpoint,
clusters.TemperatureControl.Attributes.MinTemperature,
clusters.TemperatureControl.Attributes.MaxTemperature,
),
),
]
3 changes: 3 additions & 0 deletions homeassistant/components/matter/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@
"temperature_offset": {
"name": "Temperature offset"
},
"temperature_setpoint": {
"name": "Temperature setpoint"
},
"pir_occupied_to_unoccupied_delay": {
"name": "Occupied to unoccupied delay"
},
Expand Down
Loading
Loading