Merge branch 'dev' into fix-microsign-alt1

This commit is contained in:
Jan Bouwhuis
2025-06-01 20:14:12 +02:00
committed by GitHub
296 changed files with 2665 additions and 1676 deletions

View File

@@ -0,0 +1,6 @@
{
"domain": "shelly",
"name": "shelly",
"integrations": ["shelly"],
"iot_standards": ["zwave"]
}

View File

@@ -5,23 +5,22 @@ from __future__ import annotations
from datetime import timedelta
import logging
from airthings import Airthings, AirthingsDevice, AirthingsError
from airthings import Airthings
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import CONF_SECRET, DOMAIN
from .const import CONF_SECRET
from .coordinator import AirthingsDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
PLATFORMS: list[Platform] = [Platform.SENSOR]
SCAN_INTERVAL = timedelta(minutes=6)
type AirthingsDataCoordinatorType = DataUpdateCoordinator[dict[str, AirthingsDevice]]
type AirthingsConfigEntry = ConfigEntry[AirthingsDataCoordinatorType]
type AirthingsConfigEntry = ConfigEntry[AirthingsDataUpdateCoordinator]
async def async_setup_entry(hass: HomeAssistant, entry: AirthingsConfigEntry) -> bool:
@@ -32,21 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirthingsConfigEntry) ->
async_get_clientsession(hass),
)
async def _update_method() -> dict[str, AirthingsDevice]:
"""Get the latest data from Airthings."""
try:
return await airthings.update_devices() # type: ignore[no-any-return]
except AirthingsError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err
coordinator = AirthingsDataUpdateCoordinator(hass, airthings)
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
config_entry=entry,
name=DOMAIN,
update_method=_update_method,
update_interval=SCAN_INTERVAL,
)
await coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinator

View File

@@ -0,0 +1,36 @@
"""The Airthings integration."""
from datetime import timedelta
import logging
from airthings import Airthings, AirthingsDevice, AirthingsError
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(minutes=6)
class AirthingsDataUpdateCoordinator(DataUpdateCoordinator[dict[str, AirthingsDevice]]):
"""Coordinator for Airthings data updates."""
def __init__(self, hass: HomeAssistant, airthings: Airthings) -> None:
"""Initialize the coordinator."""
super().__init__(
hass,
_LOGGER,
name=DOMAIN,
update_method=self._update_method,
update_interval=SCAN_INTERVAL,
)
self.airthings = airthings
async def _update_method(self) -> dict[str, AirthingsDevice]:
"""Get the latest data from Airthings."""
try:
return await self.airthings.update_devices() # type: ignore[no-any-return]
except AirthingsError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err

View File

@@ -19,6 +19,7 @@ from homeassistant.const import (
SIGNAL_STRENGTH_DECIBELS,
EntityCategory,
UnitOfPressure,
UnitOfSoundPressure,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -27,8 +28,9 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import AirthingsConfigEntry, AirthingsDataCoordinatorType
from . import AirthingsConfigEntry
from .const import DOMAIN
from .coordinator import AirthingsDataUpdateCoordinator
SENSORS: dict[str, SensorEntityDescription] = {
"radonShortTermAvg": SensorEntityDescription(
@@ -54,6 +56,12 @@ SENSORS: dict[str, SensorEntityDescription] = {
native_unit_of_measurement=UnitOfPressure.MBAR,
state_class=SensorStateClass.MEASUREMENT,
),
"sla": SensorEntityDescription(
key="sla",
device_class=SensorDeviceClass.SOUND_PRESSURE,
native_unit_of_measurement=UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
state_class=SensorStateClass.MEASUREMENT,
),
"battery": SensorEntityDescription(
key="battery",
device_class=SensorDeviceClass.BATTERY,
@@ -140,7 +148,7 @@ async def async_setup_entry(
class AirthingsHeaterEnergySensor(
CoordinatorEntity[AirthingsDataCoordinatorType], SensorEntity
CoordinatorEntity[AirthingsDataUpdateCoordinator], SensorEntity
):
"""Representation of a Airthings Sensor device."""
@@ -149,7 +157,7 @@ class AirthingsHeaterEnergySensor(
def __init__(
self,
coordinator: AirthingsDataCoordinatorType,
coordinator: AirthingsDataUpdateCoordinator,
airthings_device: AirthingsDevice,
entity_description: SensorEntityDescription,
) -> None:

View File

@@ -4,27 +4,114 @@
"codeowners": ["@chemelli74"],
"config_flow": true,
"dhcp": [
{ "macaddress": "007147*" },
{ "macaddress": "00FC8B*" },
{ "macaddress": "0812A5*" },
{ "macaddress": "086AE5*" },
{ "macaddress": "08849D*" },
{ "macaddress": "089115*" },
{ "macaddress": "08A6BC*" },
{ "macaddress": "08C224*" },
{ "macaddress": "0CDC91*" },
{ "macaddress": "0CEE99*" },
{ "macaddress": "1009F9*" },
{ "macaddress": "109693*" },
{ "macaddress": "10BF67*" },
{ "macaddress": "10CE02*" },
{ "macaddress": "140AC5*" },
{ "macaddress": "149138*" },
{ "macaddress": "1848BE*" },
{ "macaddress": "1C12B0*" },
{ "macaddress": "1C4D66*" },
{ "macaddress": "1C93C4*" },
{ "macaddress": "1CFE2B*" },
{ "macaddress": "244CE3*" },
{ "macaddress": "24CE33*" },
{ "macaddress": "2873F6*" },
{ "macaddress": "2C71FF*" },
{ "macaddress": "34AFB3*" },
{ "macaddress": "34D270*" },
{ "macaddress": "38F73D*" },
{ "macaddress": "3C5CC4*" },
{ "macaddress": "3CE441*" },
{ "macaddress": "440049*" },
{ "macaddress": "40A2DB*" },
{ "macaddress": "40A9CF*" },
{ "macaddress": "40B4CD*" },
{ "macaddress": "443D54*" },
{ "macaddress": "44650D*" },
{ "macaddress": "485F2D*" },
{ "macaddress": "48785E*" },
{ "macaddress": "48B423*" },
{ "macaddress": "4C1744*" },
{ "macaddress": "4CEFC0*" },
{ "macaddress": "5007C3*" },
{ "macaddress": "50D45C*" },
{ "macaddress": "50DCE7*" },
{ "macaddress": "50F5DA*" },
{ "macaddress": "5C415A*" },
{ "macaddress": "6837E9*" },
{ "macaddress": "6854FD*" },
{ "macaddress": "689A87*" },
{ "macaddress": "68B691*" },
{ "macaddress": "68DBF5*" },
{ "macaddress": "68F63B*" },
{ "macaddress": "6C0C9A*" },
{ "macaddress": "6C5697*" },
{ "macaddress": "7458F3*" },
{ "macaddress": "74C246*" },
{ "macaddress": "74D637*" },
{ "macaddress": "74E20C*" },
{ "macaddress": "74ECB2*" },
{ "macaddress": "786C84*" },
{ "macaddress": "78A03F*" },
{ "macaddress": "7C6166*" },
{ "macaddress": "7C6305*" },
{ "macaddress": "7CD566*" },
{ "macaddress": "8871E5*" },
{ "macaddress": "901195*" },
{ "macaddress": "90235B*" },
{ "macaddress": "90A822*" },
{ "macaddress": "90F82E*" },
{ "macaddress": "943A91*" },
{ "macaddress": "98226E*" },
{ "macaddress": "98CCF3*" },
{ "macaddress": "9CC8E9*" },
{ "macaddress": "A002DC*" },
{ "macaddress": "A0D2B1*" },
{ "macaddress": "A40801*" },
{ "macaddress": "A8E621*" },
{ "macaddress": "AC416A*" },
{ "macaddress": "AC63BE*" },
{ "macaddress": "ACCCFC*" },
{ "macaddress": "B0739C*" },
{ "macaddress": "B0CFCB*" },
{ "macaddress": "B0F7C4*" },
{ "macaddress": "B85F98*" },
{ "macaddress": "C091B9*" },
{ "macaddress": "C095CF*" },
{ "macaddress": "C49500*" },
{ "macaddress": "C86C3D*" },
{ "macaddress": "CC9EA2*" },
{ "macaddress": "CCF735*" },
{ "macaddress": "DC54D7*" },
{ "macaddress": "D8BE65*" },
{ "macaddress": "D8FBD6*" },
{ "macaddress": "DC91BF*" },
{ "macaddress": "DCA0D0*" },
{ "macaddress": "E0F728*" },
{ "macaddress": "EC2BEB*" },
{ "macaddress": "F02F9E*" }
{ "macaddress": "EC8AC4*" },
{ "macaddress": "ECA138*" },
{ "macaddress": "F02F9E*" },
{ "macaddress": "F0272D*" },
{ "macaddress": "F0F0A4*" },
{ "macaddress": "F4032A*" },
{ "macaddress": "F854B8*" },
{ "macaddress": "FC492D*" },
{ "macaddress": "FC65DE*" },
{ "macaddress": "FCA183*" },
{ "macaddress": "FCE9D8*" }
],
"documentation": "https://www.home-assistant.io/integrations/amazon_devices",
"integration_type": "hub",

View File

@@ -7,5 +7,5 @@
"integration_type": "device",
"iot_class": "local_push",
"loggers": ["pyaprilaire"],
"requirements": ["pyaprilaire==0.9.0"]
"requirements": ["pyaprilaire==0.9.1"]
}

View File

@@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/conversation",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["hassil==2.2.3", "home-assistant-intents==2025.5.7"]
"requirements": ["hassil==2.2.3", "home-assistant-intents==2025.5.28"]
}

View File

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

View File

@@ -21,7 +21,11 @@ from homeassistant.components.light import (
LightEntity,
)
from homeassistant.const import CONF_API_KEY, CONF_DEVICES, CONF_NAME
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from . import DOMAIN
if TYPE_CHECKING:
from homeassistant.core import HomeAssistant
@@ -90,6 +94,21 @@ def setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up an Decora switch."""
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": "Leviton Decora",
},
)
lights = []
for address, device_config in config[CONF_DEVICES].items():
device = {}

View File

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

View File

@@ -21,6 +21,6 @@
"documentation": "https://www.home-assistant.io/integrations/home_connect",
"iot_class": "cloud_push",
"loggers": ["aiohomeconnect"],
"requirements": ["aiohomeconnect==0.17.0"],
"requirements": ["aiohomeconnect==0.17.1"],
"zeroconf": ["_homeconnect._tcp.local."]
}

View File

@@ -18,6 +18,10 @@
"title": "The {integration_title} YAML configuration is being removed",
"description": "Configuring {integration_title} using YAML is being removed.\n\nYour existing YAML configuration has been imported into the UI automatically.\n\nRemove the `{domain}` configuration from your configuration.yaml file and restart Home Assistant to fix this issue."
},
"deprecated_system_packages_config_flow_integration": {
"title": "The {integration_title} integration is being removed",
"description": "The {integration_title} integration is being removed as it requires additional system packages, which can't be installed on supported Home Assistant installations. Remove all \"{integration_title}\" config entries to fix this issue."
},
"deprecated_system_packages_yaml_integration": {
"title": "The {integration_title} integration is being removed",
"description": "The {integration_title} integration is being removed as it requires additional system packages, which can't be installed on supported Home Assistant installations. Remove the `{domain}` configuration from your configuration.yaml file and restart Home Assistant to fix this issue."

View File

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

View File

@@ -3,7 +3,6 @@
from __future__ import annotations
from logging import getLogger
import mimetypes
from aiohttp.web import HTTPNotFound, Request, Response, StreamResponse
from aioimmich.exceptions import ImmichError
@@ -30,11 +29,8 @@ LOGGER = getLogger(__name__)
async def async_get_media_source(hass: HomeAssistant) -> MediaSource:
"""Set up Immich media source."""
entries = hass.config_entries.async_entries(
DOMAIN, include_disabled=False, include_ignore=False
)
hass.http.register_view(ImmichMediaView(hass))
return ImmichMediaSource(hass, entries)
return ImmichMediaSource(hass)
class ImmichMediaSourceIdentifier:
@@ -42,12 +38,14 @@ class ImmichMediaSourceIdentifier:
def __init__(self, identifier: str) -> None:
"""Split identifier into parts."""
parts = identifier.split("/")
# coonfig_entry.unique_id/album_id/asset_it/filename
parts = identifier.split("|")
# config_entry.unique_id|collection|collection_id|asset_id|file_name|mime_type
self.unique_id = parts[0]
self.album_id = parts[1] if len(parts) > 1 else None
self.asset_id = parts[2] if len(parts) > 2 else None
self.file_name = parts[3] if len(parts) > 2 else None
self.collection = parts[1] if len(parts) > 1 else None
self.collection_id = parts[2] if len(parts) > 2 else None
self.asset_id = parts[3] if len(parts) > 3 else None
self.file_name = parts[4] if len(parts) > 3 else None
self.mime_type = parts[5] if len(parts) > 3 else None
class ImmichMediaSource(MediaSource):
@@ -55,18 +53,17 @@ class ImmichMediaSource(MediaSource):
name = "Immich"
def __init__(self, hass: HomeAssistant, entries: list[ConfigEntry]) -> None:
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize Immich media source."""
super().__init__(DOMAIN)
self.hass = hass
self.entries = entries
async def async_browse_media(
self,
item: MediaSourceItem,
) -> BrowseMediaSource:
"""Return media."""
if not self.hass.config_entries.async_loaded_entries(DOMAIN):
if not (entries := self.hass.config_entries.async_loaded_entries(DOMAIN)):
raise BrowseError("Immich is not configured")
return BrowseMediaSource(
domain=DOMAIN,
@@ -78,15 +75,16 @@ class ImmichMediaSource(MediaSource):
can_expand=True,
children_media_class=MediaClass.DIRECTORY,
children=[
*await self._async_build_immich(item),
*await self._async_build_immich(item, entries),
],
)
async def _async_build_immich(
self, item: MediaSourceItem
self, item: MediaSourceItem, entries: list[ConfigEntry]
) -> list[BrowseMediaSource]:
"""Handle browsing different immich instances."""
if not item.identifier:
LOGGER.debug("Render all Immich instances")
return [
BrowseMediaSource(
domain=DOMAIN,
@@ -97,7 +95,7 @@ class ImmichMediaSource(MediaSource):
can_play=False,
can_expand=True,
)
for entry in self.entries
for entry in entries
]
identifier = ImmichMediaSourceIdentifier(item.identifier)
entry: ImmichConfigEntry | None = (
@@ -108,8 +106,22 @@ class ImmichMediaSource(MediaSource):
assert entry
immich_api = entry.runtime_data.api
if identifier.album_id is None:
# Get Albums
if identifier.collection is None:
LOGGER.debug("Render all collections for %s", entry.title)
return [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{identifier.unique_id}|albums",
media_class=MediaClass.DIRECTORY,
media_content_type=MediaClass.IMAGE,
title="albums",
can_play=False,
can_expand=True,
)
]
if identifier.collection_id is None:
LOGGER.debug("Render all albums for %s", entry.title)
try:
albums = await immich_api.albums.async_get_all_albums()
except ImmichError:
@@ -118,21 +130,25 @@ class ImmichMediaSource(MediaSource):
return [
BrowseMediaSource(
domain=DOMAIN,
identifier=f"{item.identifier}/{album.album_id}",
identifier=f"{identifier.unique_id}|albums|{album.album_id}",
media_class=MediaClass.DIRECTORY,
media_content_type=MediaClass.IMAGE,
title=album.name,
can_play=False,
can_expand=True,
thumbnail=f"/immich/{identifier.unique_id}/{album.thumbnail_asset_id}/thumb.jpg/thumbnail",
thumbnail=f"/immich/{identifier.unique_id}/{album.thumbnail_asset_id}/thumbnail/image/jpg",
)
for album in albums
]
# Request items of album
LOGGER.debug(
"Render all assets of album %s for %s",
identifier.collection_id,
entry.title,
)
try:
album_info = await immich_api.albums.async_get_album_info(
identifier.album_id
identifier.collection_id
)
except ImmichError:
return []
@@ -141,17 +157,18 @@ class ImmichMediaSource(MediaSource):
BrowseMediaSource(
domain=DOMAIN,
identifier=(
f"{identifier.unique_id}/"
f"{identifier.album_id}/"
f"{asset.asset_id}/"
f"{asset.file_name}"
f"{identifier.unique_id}|albums|"
f"{identifier.collection_id}|"
f"{asset.asset_id}|"
f"{asset.file_name}|"
f"{asset.mime_type}"
),
media_class=MediaClass.IMAGE,
media_content_type=asset.mime_type,
title=asset.file_name,
can_play=False,
can_expand=False,
thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/{asset.file_name}/thumbnail",
thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail/{asset.mime_type}",
)
for asset in album_info.assets
if asset.mime_type.startswith("image/")
@@ -161,17 +178,18 @@ class ImmichMediaSource(MediaSource):
BrowseMediaSource(
domain=DOMAIN,
identifier=(
f"{identifier.unique_id}/"
f"{identifier.album_id}/"
f"{asset.asset_id}/"
f"{asset.file_name}"
f"{identifier.unique_id}|albums|"
f"{identifier.collection_id}|"
f"{asset.asset_id}|"
f"{asset.file_name}|"
f"{asset.mime_type}"
),
media_class=MediaClass.VIDEO,
media_content_type=asset.mime_type,
title=asset.file_name,
can_play=True,
can_expand=False,
thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail.jpg/thumbnail",
thumbnail=f"/immich/{identifier.unique_id}/{asset.asset_id}/thumbnail/image/jpeg",
)
for asset in album_info.assets
if asset.mime_type.startswith("video/")
@@ -181,17 +199,23 @@ class ImmichMediaSource(MediaSource):
async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
"""Resolve media to a url."""
try:
identifier = ImmichMediaSourceIdentifier(item.identifier)
if identifier.file_name is None:
raise Unresolvable("No file name")
mime_type, _ = mimetypes.guess_type(identifier.file_name)
if not isinstance(mime_type, str):
raise Unresolvable("No file extension")
except IndexError as err:
raise Unresolvable(
f"Could not parse identifier: {item.identifier}"
) from err
if identifier.mime_type is None:
raise Unresolvable(
f"Could not resolve identifier that has no mime-type: {item.identifier}"
)
return PlayMedia(
(
f"/immich/{identifier.unique_id}/{identifier.asset_id}/{identifier.file_name}/fullsize"
f"/immich/{identifier.unique_id}/{identifier.asset_id}/fullsize/{identifier.mime_type}"
),
mime_type,
identifier.mime_type,
)
@@ -212,10 +236,10 @@ class ImmichMediaView(HomeAssistantView):
if not self.hass.config_entries.async_loaded_entries(DOMAIN):
raise HTTPNotFound
asset_id, file_name, size = location.split("/")
mime_type, _ = mimetypes.guess_type(file_name)
if not isinstance(mime_type, str):
raise HTTPNotFound
try:
asset_id, size, mime_type_base, mime_type_format = location.split("/")
except ValueError as err:
raise HTTPNotFound from err
entry: ImmichConfigEntry | None = (
self.hass.config_entries.async_entry_for_domain_unique_id(
@@ -226,7 +250,7 @@ class ImmichMediaView(HomeAssistantView):
immich_api = entry.runtime_data.api
# stream response for videos
if mime_type.startswith("video/"):
if mime_type_base == "video":
try:
resp = await immich_api.assets.async_play_video_stream(asset_id)
except ImmichError as exc:
@@ -243,4 +267,4 @@ class ImmichMediaView(HomeAssistantView):
image = await immich_api.assets.async_view_asset(asset_id, size)
except ImmichError as exc:
raise HTTPNotFound from exc
return Response(body=image, content_type=mime_type)
return Response(body=image, content_type=f"{mime_type_base}/{mime_type_format}")

View File

@@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["pyiskra"],
"requirements": ["pyiskra==0.1.15"]
"requirements": ["pyiskra==0.1.19"]
}

View File

@@ -7,7 +7,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from .client_wrapper import CannotConnect, InvalidAuth, create_client, validate_input
from .const import CONF_CLIENT_DEVICE_ID, DOMAIN, PLATFORMS
from .const import CONF_CLIENT_DEVICE_ID, DEFAULT_NAME, DOMAIN, PLATFORMS
from .coordinator import JellyfinConfigEntry, JellyfinDataUpdateCoordinator
@@ -35,9 +35,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: JellyfinConfigEntry) ->
coordinator = JellyfinDataUpdateCoordinator(
hass, entry, client, server_info, user_id
)
await coordinator.async_config_entry_first_refresh()
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
entry_type=dr.DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.server_id)},
manufacturer=DEFAULT_NAME,
name=coordinator.server_name,
sw_version=coordinator.server_version,
)
entry.runtime_data = coordinator
entry.async_on_unload(client.stop)

View File

@@ -4,10 +4,10 @@ from __future__ import annotations
from typing import Any
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DEFAULT_NAME, DOMAIN
from .const import DOMAIN
from .coordinator import JellyfinDataUpdateCoordinator
@@ -24,11 +24,7 @@ class JellyfinServerEntity(JellyfinEntity):
"""Initialize the Jellyfin entity."""
super().__init__(coordinator)
self._attr_device_info = DeviceInfo(
entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, coordinator.server_id)},
manufacturer=DEFAULT_NAME,
name=coordinator.server_name,
sw_version=coordinator.server_version,
)

View File

@@ -11,8 +11,9 @@ from homeassistant.const import (
SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_UP,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from homeassistant.helpers.typing import ConfigType
DOMAIN = "keyboard"
@@ -24,6 +25,20 @@ CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Listen for keyboard events."""
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": "Keyboard",
},
)
keyboard = PyKeyboard()
keyboard.special_key_assignment()

View File

@@ -20,8 +20,8 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
from .const import DOMAIN
SCAN_INTERVAL = timedelta(seconds=15)
SETTINGS_UPDATE_INTERVAL = timedelta(hours=1)
SCHEDULE_UPDATE_INTERVAL = timedelta(minutes=5)
SETTINGS_UPDATE_INTERVAL = timedelta(hours=8)
SCHEDULE_UPDATE_INTERVAL = timedelta(minutes=30)
STATISTICS_UPDATE_INTERVAL = timedelta(minutes=15)
_LOGGER = logging.getLogger(__name__)

View File

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

View File

@@ -7,6 +7,6 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["linkplay"],
"requirements": ["python-linkplay==0.2.8"],
"requirements": ["python-linkplay==0.2.9"],
"zeroconf": ["_linkplay._tcp.local."]
}

View File

@@ -7,8 +7,9 @@ import time
import lirc
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import HomeAssistant
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__)
@@ -26,6 +27,20 @@ CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the LIRC capability."""
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": "LIRC",
},
)
# blocking=True gives unexpected behavior (multiple responses for 1 press)
# also by not blocking, we allow hass to shut down the thread gracefully
# on exit.

View File

@@ -40,7 +40,7 @@ SUPPORT_FLAGS = (
PRESET_MODES = [PRESET_NONE, PRESET_COMFORT, PRESET_ECO, PRESET_AWAY]
MIN_TEMPERATURE = 7
MAX_TEMPERATURE = 40
MAX_TEMPERATURE = 30
async def async_setup_entry(

View File

@@ -7,5 +7,5 @@
"documentation": "https://www.home-assistant.io/integrations/opower",
"iot_class": "cloud_polling",
"loggers": ["opower"],
"requirements": ["opower==0.12.2"]
"requirements": ["opower==0.12.3"]
}

View File

@@ -15,5 +15,5 @@
"integration_type": "device",
"iot_class": "local_push",
"quality_scale": "bronze",
"requirements": ["pyprobeplus==1.0.0"]
"requirements": ["pyprobeplus==1.0.1"]
}

View File

@@ -7,7 +7,7 @@
"iot_class": "local_push",
"quality_scale": "internal",
"requirements": [
"SQLAlchemy==2.0.40",
"SQLAlchemy==2.0.41",
"fnv-hash-fast==1.5.0",
"psutil-home-assistant==0.0.1"
]

View File

@@ -233,6 +233,14 @@ async def async_setup_entry(
"privacy_mode_change", async_privacy_mode_change, 623
)
# ensure host device is setup before connected camera devices that use via_device
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={(DOMAIN, host.unique_id)},
connections={(dr.CONNECTION_NETWORK_MAC, host.api.mac_address)},
)
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
config_entry.async_on_unload(

View File

@@ -462,6 +462,12 @@
"doorbell_button_sound": {
"default": "mdi:volume-high"
},
"hardwired_chime_enabled": {
"default": "mdi:bell",
"state": {
"off": "mdi:bell-off"
}
},
"hdr": {
"default": "mdi:hdr"
},

View File

@@ -19,5 +19,5 @@
"iot_class": "local_push",
"loggers": ["reolink_aio"],
"quality_scale": "platinum",
"requirements": ["reolink-aio==0.13.3"]
"requirements": ["reolink-aio==0.13.4"]
}

View File

@@ -910,6 +910,9 @@
"auto_focus": {
"name": "Auto focus"
},
"hardwired_chime_enabled": {
"name": "Hardwired chime enabled"
},
"guard_return": {
"name": "Guard return"
},

View File

@@ -216,6 +216,16 @@ SWITCH_ENTITIES = (
value=lambda api, ch: api.baichuan.privacy_mode(ch),
method=lambda api, ch, value: api.baichuan.set_privacy_mode(ch, value),
),
ReolinkSwitchEntityDescription(
key="hardwired_chime_enabled",
cmd_key="483",
translation_key="hardwired_chime_enabled",
entity_category=EntityCategory.CONFIG,
entity_registry_enabled_default=False,
supported=lambda api, ch: api.supported(ch, "hardwired_chime"),
value=lambda api, ch: api.baichuan.hardwired_chime_enabled(ch),
method=lambda api, ch, value: api.baichuan.set_ding_dong_ctrl(ch, enable=value),
),
)
NVR_SWITCH_ENTITIES = (

View File

@@ -52,6 +52,7 @@ class PlaybackProxyView(HomeAssistantView):
verify_ssl=False,
ssl_cipher=SSLCipherList.INSECURE,
)
self._vod_type: str | None = None
async def get(
self,
@@ -68,6 +69,8 @@ class PlaybackProxyView(HomeAssistantView):
filename_decoded = urlsafe_b64decode(filename.encode("utf-8")).decode("utf-8")
ch = int(channel)
if self._vod_type is not None:
vod_type = self._vod_type
try:
host = get_host(self.hass, config_entry_id)
except Unresolvable:
@@ -127,6 +130,25 @@ class PlaybackProxyView(HomeAssistantView):
"apolication/octet-stream",
]:
err_str = f"Reolink playback expected video/mp4 but got {reolink_response.content_type}"
if (
reolink_response.content_type == "video/x-flv"
and vod_type == VodRequestType.PLAYBACK.value
):
# next time use DOWNLOAD immediately
self._vod_type = VodRequestType.DOWNLOAD.value
_LOGGER.debug(
"%s, retrying using download instead of playback cmd", err_str
)
return await self.get(
request,
config_entry_id,
channel,
stream_res,
self._vod_type,
filename,
retry,
)
_LOGGER.error(err_str)
if reolink_response.content_type == "text/html":
text = await reolink_response.text()
@@ -140,7 +162,10 @@ class PlaybackProxyView(HomeAssistantView):
reolink_response.reason,
response_headers,
)
response_headers["Content-Type"] = "video/mp4"
if "Content-Type" not in response_headers:
response_headers["Content-Type"] = reolink_response.content_type
if response_headers["Content-Type"] == "apolication/octet-stream":
response_headers["Content-Type"] = "application/octet-stream"
response = web.StreamResponse(
status=reolink_response.status,

View File

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

View File

@@ -6,9 +6,14 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE, CONF_NAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
from homeassistant.helpers.typing import ConfigType
from .const import (
@@ -41,6 +46,7 @@ CONFIG_SCHEMA = vol.Schema(
},
extra=vol.ALLOW_EXTRA,
)
DEPRECATED_ISSUE_ID = f"deprecated_system_packages_config_flow_integration_{DOMAIN}"
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
@@ -52,6 +58,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Configure Gammu state machine."""
async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
DEPRECATED_ISSUE_ID,
breaks_in_ha_version="2025.12.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="deprecated_system_packages_config_flow_integration",
translation_placeholders={
"integration_title": "SMS notifications via GSM-modem",
},
)
device = entry.data[CONF_DEVICE]
connection_mode = "at"
@@ -101,4 +120,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
gateway = hass.data[DOMAIN].pop(SMS_GATEWAY)[GATEWAY]
await gateway.terminate_async()
if not hass.config_entries.async_loaded_entries(DOMAIN):
async_delete_issue(hass, HOMEASSISTANT_DOMAIN, DEPRECATED_ISSUE_ID)
return unload_ok

View File

@@ -7,8 +7,13 @@ import logging
import voluptuous as vol
from homeassistant.components import mqtt
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import (
DOMAIN as HOMEASSISTANT_DOMAIN,
HomeAssistant,
ServiceCall,
)
from homeassistant.helpers import config_validation as cv, intent
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.typing import ConfigType
DOMAIN = "snips"
@@ -91,6 +96,20 @@ SERVICE_SCHEMA_FEEDBACK = vol.Schema(
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Activate Snips component."""
async_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": "Snips",
},
)
# Make sure MQTT integration is enabled and the client is available
if not await mqtt.async_wait_for_mqtt_client(hass):

View File

@@ -6,5 +6,5 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sql",
"iot_class": "local_polling",
"requirements": ["SQLAlchemy==2.0.40", "sqlparse==0.5.0"]
"requirements": ["SQLAlchemy==2.0.41", "sqlparse==0.5.0"]
}

View File

@@ -7,7 +7,13 @@ from dataclasses import dataclass, field
from logging import getLogger
from aiohttp import web
from switchbot_api import CannotConnect, Device, InvalidAuth, Remote, SwitchBotAPI
from switchbot_api import (
Device,
Remote,
SwitchBotAPI,
SwitchBotAuthenticationError,
SwitchBotConnectionError,
)
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
@@ -175,12 +181,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
api = SwitchBotAPI(token=token, secret=secret)
try:
devices = await api.list_devices()
except InvalidAuth as ex:
except SwitchBotAuthenticationError as ex:
_LOGGER.error(
"Invalid authentication while connecting to SwitchBot API: %s", ex
)
return False
except CannotConnect as ex:
except SwitchBotConnectionError as ex:
raise ConfigEntryNotReady from ex
_LOGGER.debug("Devices: %s", devices)
coordinators_by_id: dict[str, SwitchBotCoordinator] = {}

View File

@@ -3,7 +3,11 @@
from logging import getLogger
from typing import Any
from switchbot_api import CannotConnect, InvalidAuth, SwitchBotAPI
from switchbot_api import (
SwitchBotAPI,
SwitchBotAuthenticationError,
SwitchBotConnectionError,
)
import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@@ -36,9 +40,9 @@ class SwitchBotCloudConfigFlow(ConfigFlow, domain=DOMAIN):
await SwitchBotAPI(
token=user_input[CONF_API_TOKEN], secret=user_input[CONF_API_KEY]
).list_devices()
except CannotConnect:
except SwitchBotConnectionError:
errors["base"] = "cannot_connect"
except InvalidAuth:
except SwitchBotAuthenticationError:
errors["base"] = "invalid_auth"
except Exception:
_LOGGER.exception("Unexpected exception")

View File

@@ -4,7 +4,7 @@ from asyncio import timeout
from logging import getLogger
from typing import Any
from switchbot_api import CannotConnect, Device, Remote, SwitchBotAPI
from switchbot_api import Device, Remote, SwitchBotAPI, SwitchBotConnectionError
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
@@ -70,5 +70,5 @@ class SwitchBotCoordinator(DataUpdateCoordinator[Status]):
status: Status = await self._api.get_status(self._device_id)
_LOGGER.debug("Refreshing %s with %s", self._device_id, status)
return status
except CannotConnect as err:
except SwitchBotConnectionError as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err

View File

@@ -8,5 +8,5 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"loggers": ["switchbot_api"],
"requirements": ["switchbot-api==2.3.1"]
"requirements": ["switchbot-api==2.4.0"]
}

View File

@@ -8,5 +8,5 @@
"iot_class": "local_push",
"loggers": ["aiotedee"],
"quality_scale": "platinum",
"requirements": ["aiotedee==0.2.20"]
"requirements": ["aiotedee==0.2.23"]
}

View File

@@ -1 +1,4 @@
"""The tensorflow component."""
DOMAIN = "tensorflow"
CONF_GRAPH = "graph"

View File

@@ -26,15 +26,21 @@ from homeassistant.const import (
CONF_SOURCE,
EVENT_HOMEASSISTANT_START,
)
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.core import (
DOMAIN as HOMEASSISTANT_DOMAIN,
HomeAssistant,
split_entity_id,
)
from homeassistant.helpers import config_validation as cv, template
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, create_issue
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util.pil import draw_box
from . import CONF_GRAPH, DOMAIN
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
DOMAIN = "tensorflow"
_LOGGER = logging.getLogger(__name__)
ATTR_MATCHES = "matches"
@@ -47,7 +53,6 @@ CONF_BOTTOM = "bottom"
CONF_CATEGORIES = "categories"
CONF_CATEGORY = "category"
CONF_FILE_OUT = "file_out"
CONF_GRAPH = "graph"
CONF_LABELS = "labels"
CONF_LABEL_OFFSET = "label_offset"
CONF_LEFT = "left"
@@ -110,6 +115,21 @@ def setup_platform(
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the TensorFlow image processing platform."""
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": "Tensorflow",
},
)
model_config = config[CONF_MODEL]
model_dir = model_config.get(CONF_MODEL_DIR) or hass.config.path("tensorflow")
labels = model_config.get(CONF_LABELS) or hass.config.path(

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.0.17"]
"requirements": ["tesla-fleet-api==1.1.1"]
}

View File

@@ -125,6 +125,9 @@ 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 != "Unknown")
),
entity_category=EntityCategory.DIAGNOSTIC,
device_class=BinarySensorDeviceClass.CONNECTIVITY,
),

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.0.17", "teslemetry-stream==0.7.9"]
"requirements": ["tesla-fleet-api==1.1.1", "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.0.17"]
"requirements": ["tessie-api==0.1.1", "tesla-fleet-api==1.1.1"]
}

View File

@@ -20,6 +20,10 @@ STATES = {
"Stopped": MediaPlayerState.IDLE,
}
# Tesla uses 31 steps, in 0.333 increments up to 10.333
VOLUME_STEP = 1 / 31
VOLUME_FACTOR = 31 / 3 # 10.333
PARALLEL_UPDATES = 0
@@ -38,6 +42,7 @@ class TessieMediaEntity(TessieEntity, MediaPlayerEntity):
"""Vehicle Location Media Class."""
_attr_device_class = MediaPlayerDeviceClass.SPEAKER
_attr_volume_step = VOLUME_STEP
def __init__(
self,
@@ -57,9 +62,7 @@ class TessieMediaEntity(TessieEntity, MediaPlayerEntity):
@property
def volume_level(self) -> float:
"""Volume level of the media player (0..1)."""
return self.get("vehicle_state_media_info_audio_volume", 0) / self.get(
"vehicle_state_media_info_audio_volume_max", 10.333333
)
return self.get("vehicle_state_media_info_audio_volume", 0) / VOLUME_FACTOR
@property
def media_duration(self) -> int | None:

View File

@@ -94,21 +94,59 @@ def _get_obj_holidays(
language=language,
categories=set_categories,
)
supported_languages = obj_holidays.supported_languages
default_language = obj_holidays.default_language
if default_language and not language:
# If no language is set, use the default language
LOGGER.debug("Changing language from None to %s", default_language)
return country_holidays( # Return default if no language
country,
subdiv=province,
years=year,
language=default_language,
categories=set_categories,
)
if (
(supported_languages := obj_holidays.supported_languages)
default_language
and language
and language not in supported_languages
and language.startswith("en")
):
# If language does not match supported languages, use the first English variant
if default_language.startswith("en"):
LOGGER.debug("Changing language from %s to %s", language, default_language)
return country_holidays( # Return default English if default language
country,
subdiv=province,
years=year,
language=default_language,
categories=set_categories,
)
for lang in supported_languages:
if lang.startswith("en"):
obj_holidays = country_holidays(
LOGGER.debug("Changing language from %s to %s", language, lang)
return country_holidays(
country,
subdiv=province,
years=year,
language=lang,
categories=set_categories,
)
LOGGER.debug("Changing language from %s to %s", language, lang)
if default_language and language and language not in supported_languages:
# If language does not match supported languages, use the default language
LOGGER.debug("Changing language from %s to %s", language, default_language)
return country_holidays( # Return default English if default language
country,
subdiv=province,
years=year,
language=default_language,
categories=set_categories,
)
return obj_holidays

View File

@@ -67,8 +67,7 @@ def add_province_and_language_to_schema(
_country = country_holidays(country=country)
if country_default_language := (_country.default_language):
selectable_languages = _country.supported_languages
new_selectable_languages = list(selectable_languages)
new_selectable_languages = list(_country.supported_languages)
language_schema = {
vol.Optional(
CONF_LANGUAGE, default=country_default_language
@@ -154,19 +153,7 @@ def validate_custom_dates(user_input: dict[str, Any]) -> None:
years=year,
language=language,
)
if (
(supported_languages := obj_holidays.supported_languages)
and language
and language.startswith("en")
):
for lang in supported_languages:
if lang.startswith("en"):
obj_holidays = country_holidays(
country,
subdiv=province,
years=year,
language=lang,
)
else:
obj_holidays = HolidayBase(years=year)

View File

@@ -51,7 +51,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ZimiConfigEntry) -> bool
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, api.mac)},
manufacturer=api.brand,
name=f"{api.network_name}",
name=api.network_name,
model="Zimi Cloud Connect",
sw_version=api.firmware_version,
connections={(CONNECTION_NETWORK_MAC, api.mac)},

View File

@@ -32,7 +32,7 @@ async def async_setup_entry(
]
lights.extend(
[ZimiDimmer(device, api) for device in api.lights if device.type == "dimmer"]
ZimiDimmer(device, api) for device in api.lights if device.type == "dimmer"
)
async_add_entities(lights)
@@ -81,8 +81,6 @@ class ZimiDimmer(ZimiLight):
super().__init__(device, api)
self._attr_color_mode = ColorMode.BRIGHTNESS
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
if self._device.type != "dimmer":
raise ValueError("ZimiDimmer needs a dimmable light")
async def async_turn_on(self, **kwargs: Any) -> None:
"""Instruct the light to turn on (with optional brightness)."""

View File

@@ -26,22 +26,158 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"domain": "airzone",
"macaddress": "E84F25*",
},
{
"domain": "amazon_devices",
"macaddress": "007147*",
},
{
"domain": "amazon_devices",
"macaddress": "00FC8B*",
},
{
"domain": "amazon_devices",
"macaddress": "0812A5*",
},
{
"domain": "amazon_devices",
"macaddress": "086AE5*",
},
{
"domain": "amazon_devices",
"macaddress": "08849D*",
},
{
"domain": "amazon_devices",
"macaddress": "089115*",
},
{
"domain": "amazon_devices",
"macaddress": "08A6BC*",
},
{
"domain": "amazon_devices",
"macaddress": "08C224*",
},
{
"domain": "amazon_devices",
"macaddress": "0CDC91*",
},
{
"domain": "amazon_devices",
"macaddress": "0CEE99*",
},
{
"domain": "amazon_devices",
"macaddress": "1009F9*",
},
{
"domain": "amazon_devices",
"macaddress": "109693*",
},
{
"domain": "amazon_devices",
"macaddress": "10BF67*",
},
{
"domain": "amazon_devices",
"macaddress": "10CE02*",
},
{
"domain": "amazon_devices",
"macaddress": "140AC5*",
},
{
"domain": "amazon_devices",
"macaddress": "149138*",
},
{
"domain": "amazon_devices",
"macaddress": "1848BE*",
},
{
"domain": "amazon_devices",
"macaddress": "1C12B0*",
},
{
"domain": "amazon_devices",
"macaddress": "1C4D66*",
},
{
"domain": "amazon_devices",
"macaddress": "1C93C4*",
},
{
"domain": "amazon_devices",
"macaddress": "1CFE2B*",
},
{
"domain": "amazon_devices",
"macaddress": "244CE3*",
},
{
"domain": "amazon_devices",
"macaddress": "24CE33*",
},
{
"domain": "amazon_devices",
"macaddress": "2873F6*",
},
{
"domain": "amazon_devices",
"macaddress": "2C71FF*",
},
{
"domain": "amazon_devices",
"macaddress": "34AFB3*",
},
{
"domain": "amazon_devices",
"macaddress": "34D270*",
},
{
"domain": "amazon_devices",
"macaddress": "38F73D*",
},
{
"domain": "amazon_devices",
"macaddress": "3C5CC4*",
},
{
"domain": "amazon_devices",
"macaddress": "3CE441*",
},
{
"domain": "amazon_devices",
"macaddress": "440049*",
},
{
"domain": "amazon_devices",
"macaddress": "40A2DB*",
},
{
"domain": "amazon_devices",
"macaddress": "40A9CF*",
},
{
"domain": "amazon_devices",
"macaddress": "40B4CD*",
},
{
"domain": "amazon_devices",
"macaddress": "443D54*",
},
{
"domain": "amazon_devices",
"macaddress": "44650D*",
},
{
"domain": "amazon_devices",
"macaddress": "485F2D*",
},
{
"domain": "amazon_devices",
"macaddress": "48785E*",
},
{
"domain": "amazon_devices",
"macaddress": "48B423*",
@@ -50,6 +186,14 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"domain": "amazon_devices",
"macaddress": "4C1744*",
},
{
"domain": "amazon_devices",
"macaddress": "4CEFC0*",
},
{
"domain": "amazon_devices",
"macaddress": "5007C3*",
},
{
"domain": "amazon_devices",
"macaddress": "50D45C*",
@@ -58,6 +202,34 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"domain": "amazon_devices",
"macaddress": "50DCE7*",
},
{
"domain": "amazon_devices",
"macaddress": "50F5DA*",
},
{
"domain": "amazon_devices",
"macaddress": "5C415A*",
},
{
"domain": "amazon_devices",
"macaddress": "6837E9*",
},
{
"domain": "amazon_devices",
"macaddress": "6854FD*",
},
{
"domain": "amazon_devices",
"macaddress": "689A87*",
},
{
"domain": "amazon_devices",
"macaddress": "68B691*",
},
{
"domain": "amazon_devices",
"macaddress": "68DBF5*",
},
{
"domain": "amazon_devices",
"macaddress": "68F63B*",
@@ -66,18 +238,70 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"domain": "amazon_devices",
"macaddress": "6C0C9A*",
},
{
"domain": "amazon_devices",
"macaddress": "6C5697*",
},
{
"domain": "amazon_devices",
"macaddress": "7458F3*",
},
{
"domain": "amazon_devices",
"macaddress": "74C246*",
},
{
"domain": "amazon_devices",
"macaddress": "74D637*",
},
{
"domain": "amazon_devices",
"macaddress": "74E20C*",
},
{
"domain": "amazon_devices",
"macaddress": "74ECB2*",
},
{
"domain": "amazon_devices",
"macaddress": "786C84*",
},
{
"domain": "amazon_devices",
"macaddress": "78A03F*",
},
{
"domain": "amazon_devices",
"macaddress": "7C6166*",
},
{
"domain": "amazon_devices",
"macaddress": "7C6305*",
},
{
"domain": "amazon_devices",
"macaddress": "7CD566*",
},
{
"domain": "amazon_devices",
"macaddress": "8871E5*",
},
{
"domain": "amazon_devices",
"macaddress": "901195*",
},
{
"domain": "amazon_devices",
"macaddress": "90235B*",
},
{
"domain": "amazon_devices",
"macaddress": "90A822*",
},
{
"domain": "amazon_devices",
"macaddress": "90F82E*",
},
{
"domain": "amazon_devices",
"macaddress": "943A91*",
@@ -86,30 +310,154 @@ DHCP: Final[list[dict[str, str | bool]]] = [
"domain": "amazon_devices",
"macaddress": "98226E*",
},
{
"domain": "amazon_devices",
"macaddress": "98CCF3*",
},
{
"domain": "amazon_devices",
"macaddress": "9CC8E9*",
},
{
"domain": "amazon_devices",
"macaddress": "A002DC*",
},
{
"domain": "amazon_devices",
"macaddress": "A0D2B1*",
},
{
"domain": "amazon_devices",
"macaddress": "A40801*",
},
{
"domain": "amazon_devices",
"macaddress": "A8E621*",
},
{
"domain": "amazon_devices",
"macaddress": "AC416A*",
},
{
"domain": "amazon_devices",
"macaddress": "AC63BE*",
},
{
"domain": "amazon_devices",
"macaddress": "ACCCFC*",
},
{
"domain": "amazon_devices",
"macaddress": "B0739C*",
},
{
"domain": "amazon_devices",
"macaddress": "B0CFCB*",
},
{
"domain": "amazon_devices",
"macaddress": "B0F7C4*",
},
{
"domain": "amazon_devices",
"macaddress": "B85F98*",
},
{
"domain": "amazon_devices",
"macaddress": "C091B9*",
},
{
"domain": "amazon_devices",
"macaddress": "C095CF*",
},
{
"domain": "amazon_devices",
"macaddress": "C49500*",
},
{
"domain": "amazon_devices",
"macaddress": "C86C3D*",
},
{
"domain": "amazon_devices",
"macaddress": "CC9EA2*",
},
{
"domain": "amazon_devices",
"macaddress": "CCF735*",
},
{
"domain": "amazon_devices",
"macaddress": "DC54D7*",
},
{
"domain": "amazon_devices",
"macaddress": "D8BE65*",
},
{
"domain": "amazon_devices",
"macaddress": "D8FBD6*",
},
{
"domain": "amazon_devices",
"macaddress": "DC91BF*",
},
{
"domain": "amazon_devices",
"macaddress": "DCA0D0*",
},
{
"domain": "amazon_devices",
"macaddress": "E0F728*",
},
{
"domain": "amazon_devices",
"macaddress": "EC2BEB*",
},
{
"domain": "amazon_devices",
"macaddress": "EC8AC4*",
},
{
"domain": "amazon_devices",
"macaddress": "ECA138*",
},
{
"domain": "amazon_devices",
"macaddress": "F02F9E*",
},
{
"domain": "amazon_devices",
"macaddress": "F0272D*",
},
{
"domain": "amazon_devices",
"macaddress": "F0F0A4*",
},
{
"domain": "amazon_devices",
"macaddress": "F4032A*",
},
{
"domain": "amazon_devices",
"macaddress": "F854B8*",
},
{
"domain": "amazon_devices",
"macaddress": "FC492D*",
},
{
"domain": "amazon_devices",
"macaddress": "FC65DE*",
},
{
"domain": "amazon_devices",
"macaddress": "FCA183*",
},
{
"domain": "amazon_devices",
"macaddress": "FCE9D8*",
},
{
"domain": "august",
"hostname": "connect",

View File

@@ -5867,10 +5867,18 @@
"iot_class": "local_push"
},
"shelly": {
"name": "Shelly",
"name": "shelly",
"integrations": {
"shelly": {
"integration_type": "device",
"config_flow": true,
"iot_class": "local_push"
"iot_class": "local_push",
"name": "Shelly"
}
},
"iot_standards": [
"zwave"
]
},
"shodan": {
"name": "Shodan",

View File

@@ -138,6 +138,8 @@ class DataUpdateCoordinator(BaseDataUpdateCoordinatorProtocol, Generic[_DataT]):
async def _on_hass_stop(_: Event) -> None:
"""Shutdown coordinator on HomeAssistant stop."""
# Already cleared on EVENT_HOMEASSISTANT_STOP, via async_fire_internal
self._unsub_shutdown = None
await self.async_shutdown()
self._unsub_shutdown = self.hass.bus.async_listen_once(

View File

@@ -6,7 +6,7 @@ aiodns==3.4.0
aiohasupervisor==0.3.1
aiohttp-asyncmdnsresolver==0.1.1
aiohttp-fast-zlib==0.2.3
aiohttp==3.12.2
aiohttp==3.12.6
aiohttp_cors==0.7.0
aiousbwatcher==1.1.1
aiozoneinfo==0.2.3
@@ -38,8 +38,8 @@ habluetooth==3.48.2
hass-nabucasa==0.101.0
hassil==2.2.3
home-assistant-bluetooth==1.13.1
home-assistant-frontend==20250527.0
home-assistant-intents==2025.5.7
home-assistant-frontend==20250531.0
home-assistant-intents==2025.5.28
httpx==0.28.1
ifaddr==0.2.0
Jinja2==3.1.6
@@ -63,7 +63,7 @@ PyTurboJPEG==1.7.5
PyYAML==6.0.2
requests==2.32.3
securetar==2025.2.1
SQLAlchemy==2.0.40
SQLAlchemy==2.0.41
standard-aifc==3.13.0
standard-telnetlib==3.13.0
typing-extensions>=4.13.0,<5.0
@@ -111,8 +111,8 @@ uuid==1000000000.0.0
# even newer versions seem to introduce new issues, it's useful for us to pin all these
# requirements so we can directly link HA versions to these library versions.
anyio==4.9.0
h11==0.14.0
httpcore==1.0.7
h11==0.16.0
httpcore==1.0.9
# Ensure we have a hyperframe version that works in Python 3.10
# 5.2.0 fixed a collections abc deprecation

View File

@@ -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.2",
"aiohttp==3.12.6",
"aiohttp_cors==0.7.0",
"aiohttp-fast-zlib==0.2.3",
"aiohttp-asyncmdnsresolver==0.1.1",
@@ -66,7 +66,7 @@ dependencies = [
# onboarding->cloud->assist_pipeline->conversation->home_assistant_intents. Onboarding needs
# to be setup in stage 0, but we don't want to also promote cloud with all its
# dependencies to stage 0.
"home-assistant-intents==2025.5.7",
"home-assistant-intents==2025.5.28",
"ifaddr==0.2.0",
"Jinja2==3.1.6",
"lru-dict==1.3.0",
@@ -108,7 +108,7 @@ dependencies = [
"PyYAML==6.0.2",
"requests==2.32.3",
"securetar==2025.2.1",
"SQLAlchemy==2.0.40",
"SQLAlchemy==2.0.41",
"standard-aifc==3.13.0",
"standard-telnetlib==3.13.0",
"typing-extensions>=4.13.0,<5.0",

6
requirements.txt generated
View File

@@ -5,7 +5,7 @@
# Home Assistant Core
aiodns==3.4.0
aiohasupervisor==0.3.1
aiohttp==3.12.2
aiohttp==3.12.6
aiohttp_cors==0.7.0
aiohttp-fast-zlib==0.2.3
aiohttp-asyncmdnsresolver==0.1.1
@@ -27,7 +27,7 @@ hass-nabucasa==0.101.0
hassil==2.2.3
httpx==0.28.1
home-assistant-bluetooth==1.13.1
home-assistant-intents==2025.5.7
home-assistant-intents==2025.5.28
ifaddr==0.2.0
Jinja2==3.1.6
lru-dict==1.3.0
@@ -48,7 +48,7 @@ PyTurboJPEG==1.7.5
PyYAML==6.0.2
requests==2.32.3
securetar==2025.2.1
SQLAlchemy==2.0.40
SQLAlchemy==2.0.41
standard-aifc==3.13.0
standard-telnetlib==3.13.0
typing-extensions>=4.13.0,<5.0

34
requirements_all.txt generated
View File

@@ -113,7 +113,7 @@ RtmAPI==0.7.2
# homeassistant.components.recorder
# homeassistant.components.sql
SQLAlchemy==2.0.40
SQLAlchemy==2.0.41
# homeassistant.components.tami4
Tami4EdgeAPI==3.0
@@ -265,7 +265,7 @@ aioharmony==0.5.2
aiohasupervisor==0.3.1
# homeassistant.components.home_connect
aiohomeconnect==0.17.0
aiohomeconnect==0.17.1
# homeassistant.components.homekit_controller
aiohomekit==3.2.14
@@ -280,7 +280,7 @@ aiohue==4.7.4
aioimaplib==2.0.1
# homeassistant.components.immich
aioimmich==0.6.0
aioimmich==0.7.0
# homeassistant.components.apache_kafka
aiokafka==0.10.0
@@ -405,7 +405,7 @@ aiosyncthing==0.5.1
aiotankerkoenig==0.4.2
# homeassistant.components.tedee
aiotedee==0.2.20
aiotedee==0.2.23
# homeassistant.components.tractive
aiotractive==0.6.0
@@ -759,7 +759,7 @@ dbus-fast==2.43.0
debugpy==1.8.14
# homeassistant.components.decora_wifi
# decora-wifi==1.4
decora-wifi==1.4
# homeassistant.components.decora
# decora==0.6
@@ -1164,10 +1164,10 @@ hole==0.8.0
holidays==0.73
# homeassistant.components.frontend
home-assistant-frontend==20250527.0
home-assistant-frontend==20250531.0
# homeassistant.components.conversation
home-assistant-intents==2025.5.7
home-assistant-intents==2025.5.28
# homeassistant.components.homematicip_cloud
homematicip==2.0.1.1
@@ -1617,7 +1617,7 @@ openwrt-luci-rpc==1.1.17
openwrt-ubus-rpc==0.0.2
# homeassistant.components.opower
opower==0.12.2
opower==0.12.3
# homeassistant.components.oralb
oralb-ble==0.17.6
@@ -1832,7 +1832,7 @@ pyairnow==1.2.1
pyairvisual==2023.08.1
# homeassistant.components.aprilaire
pyaprilaire==0.9.0
pyaprilaire==0.9.1
# homeassistant.components.asuswrt
pyasuswrt==0.1.21
@@ -2051,7 +2051,7 @@ pyiqvia==2022.04.0
pyirishrail==0.0.2
# homeassistant.components.iskra
pyiskra==0.1.15
pyiskra==0.1.19
# homeassistant.components.iss
pyiss==1.0.1
@@ -2096,7 +2096,7 @@ pykwb==0.0.8
pylacrosse==0.4
# homeassistant.components.lamarzocco
pylamarzocco==2.0.7
pylamarzocco==2.0.8
# homeassistant.components.lastfm
pylast==5.1.0
@@ -2251,7 +2251,7 @@ pyplaato==0.0.19
pypoint==3.0.0
# homeassistant.components.probe_plus
pyprobeplus==1.0.0
pyprobeplus==1.0.1
# homeassistant.components.profiler
pyprof2calltree==1.4.5
@@ -2353,7 +2353,7 @@ pysmhi==1.0.2
pysml==0.0.12
# homeassistant.components.smlight
pysmlight==0.2.4
pysmlight==0.2.5
# homeassistant.components.snmp
pysnmp==6.2.6
@@ -2452,7 +2452,7 @@ python-juicenet==1.1.0
python-kasa[speedups]==0.10.2
# homeassistant.components.linkplay
python-linkplay==0.2.8
python-linkplay==0.2.9
# homeassistant.components.lirc
# python-lirc==1.2.3
@@ -2652,7 +2652,7 @@ renault-api==0.3.1
renson-endura-delta==1.7.2
# homeassistant.components.reolink
reolink-aio==0.13.3
reolink-aio==0.13.4
# homeassistant.components.idteck_prox
rfk101py==0.0.1
@@ -2859,7 +2859,7 @@ surepy==0.9.0
swisshydrodata==0.1.0
# homeassistant.components.switchbot_cloud
switchbot-api==2.3.1
switchbot-api==2.4.0
# homeassistant.components.synology_srm
synology-srm==0.2.0
@@ -2900,7 +2900,7 @@ temperusb==1.6.1
# homeassistant.components.tesla_fleet
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==1.0.17
tesla-fleet-api==1.1.1
# homeassistant.components.powerwall
tesla-powerwall==0.5.2

View File

@@ -107,7 +107,7 @@ RtmAPI==0.7.2
# homeassistant.components.recorder
# homeassistant.components.sql
SQLAlchemy==2.0.40
SQLAlchemy==2.0.41
# homeassistant.components.tami4
Tami4EdgeAPI==3.0
@@ -250,7 +250,7 @@ aioharmony==0.5.2
aiohasupervisor==0.3.1
# homeassistant.components.home_connect
aiohomeconnect==0.17.0
aiohomeconnect==0.17.1
# homeassistant.components.homekit_controller
aiohomekit==3.2.14
@@ -265,7 +265,7 @@ aiohue==4.7.4
aioimaplib==2.0.1
# homeassistant.components.immich
aioimmich==0.6.0
aioimmich==0.7.0
# homeassistant.components.apache_kafka
aiokafka==0.10.0
@@ -387,7 +387,7 @@ aiosyncthing==0.5.1
aiotankerkoenig==0.4.2
# homeassistant.components.tedee
aiotedee==0.2.20
aiotedee==0.2.23
# homeassistant.components.tractive
aiotractive==0.6.0
@@ -561,6 +561,9 @@ bluecurrent-api==1.2.3
# homeassistant.components.bluemaestro
bluemaestro-ble==0.4.1
# homeassistant.components.decora
# bluepy==1.3.0
# homeassistant.components.bluetooth
bluetooth-adapters==0.21.4
@@ -655,6 +658,9 @@ dbus-fast==2.43.0
# homeassistant.components.debugpy
debugpy==1.8.14
# homeassistant.components.decora
# decora==0.6
# homeassistant.components.ecovacs
deebot-client==13.2.1
@@ -1001,10 +1007,10 @@ hole==0.8.0
holidays==0.73
# homeassistant.components.frontend
home-assistant-frontend==20250527.0
home-assistant-frontend==20250531.0
# homeassistant.components.conversation
home-assistant-intents==2025.5.7
home-assistant-intents==2025.5.28
# homeassistant.components.homematicip_cloud
homematicip==2.0.1.1
@@ -1361,7 +1367,7 @@ openhomedevice==2.2.0
openwebifpy==4.3.1
# homeassistant.components.opower
opower==0.12.2
opower==0.12.3
# homeassistant.components.oralb
oralb-ble==0.17.6
@@ -1525,7 +1531,7 @@ pyairnow==1.2.1
pyairvisual==2023.08.1
# homeassistant.components.aprilaire
pyaprilaire==0.9.0
pyaprilaire==0.9.1
# homeassistant.components.asuswrt
pyasuswrt==0.1.21
@@ -1560,6 +1566,9 @@ pybravia==0.3.4
# homeassistant.components.cloudflare
pycfdns==3.0.0
# homeassistant.components.tensorflow
# pycocotools==2.0.6
# homeassistant.components.comfoconnect
pycomfoconnect==0.5.1
@@ -1690,7 +1699,7 @@ pyipp==0.17.0
pyiqvia==2022.04.0
# homeassistant.components.iskra
pyiskra==0.1.15
pyiskra==0.1.19
# homeassistant.components.iss
pyiss==1.0.1
@@ -1726,7 +1735,7 @@ pykrakenapi==0.1.8
pykulersky==0.5.8
# homeassistant.components.lamarzocco
pylamarzocco==2.0.7
pylamarzocco==2.0.8
# homeassistant.components.lastfm
pylast==5.1.0
@@ -1860,7 +1869,7 @@ pyplaato==0.0.19
pypoint==3.0.0
# homeassistant.components.probe_plus
pyprobeplus==1.0.0
pyprobeplus==1.0.1
# homeassistant.components.profiler
pyprof2calltree==1.4.5
@@ -1941,7 +1950,7 @@ pysmhi==1.0.2
pysml==0.0.12
# homeassistant.components.smlight
pysmlight==0.2.4
pysmlight==0.2.5
# homeassistant.components.snmp
pysnmp==6.2.6
@@ -2010,7 +2019,10 @@ python-juicenet==1.1.0
python-kasa[speedups]==0.10.2
# homeassistant.components.linkplay
python-linkplay==0.2.8
python-linkplay==0.2.9
# homeassistant.components.lirc
# python-lirc==1.2.3
# homeassistant.components.matter
python-matter-server==7.0.0
@@ -2095,6 +2107,9 @@ pytrydan==0.8.0
# homeassistant.components.uptimerobot
pyuptimerobot==22.2.0
# homeassistant.components.keyboard
# pyuserinput==0.1.11
# homeassistant.components.vera
pyvera==0.3.15
@@ -2177,7 +2192,7 @@ renault-api==0.3.1
renson-endura-delta==1.7.2
# homeassistant.components.reolink
reolink-aio==0.13.3
reolink-aio==0.13.4
# homeassistant.components.rflink
rflink==0.0.66
@@ -2339,7 +2354,7 @@ subarulink==0.7.13
surepy==0.9.0
# homeassistant.components.switchbot_cloud
switchbot-api==2.3.1
switchbot-api==2.4.0
# homeassistant.components.system_bridge
systembridgeconnector==4.1.5
@@ -2359,10 +2374,13 @@ temescal==0.5
# homeassistant.components.temper
temperusb==1.6.1
# homeassistant.components.tensorflow
# tensorflow==2.5.0
# homeassistant.components.tesla_fleet
# homeassistant.components.teslemetry
# homeassistant.components.tessie
tesla-fleet-api==1.0.17
tesla-fleet-api==1.1.1
# homeassistant.components.powerwall
tesla-powerwall==0.5.2
@@ -2376,6 +2394,9 @@ teslemetry-stream==0.7.9
# homeassistant.components.tessie
tessie-api==0.1.1
# homeassistant.components.tensorflow
# tf-models-official==2.5.0
# homeassistant.components.thermobeacon
thermobeacon-ble==0.10.0

View File

@@ -27,7 +27,6 @@ EXCLUDED_REQUIREMENTS_ALL = {
"beewi-smartclim", # depends on bluepy
"bluepy",
"decora",
"decora-wifi",
"evdev",
"face-recognition",
"pybluez",
@@ -43,7 +42,6 @@ EXCLUDED_REQUIREMENTS_ALL = {
# Requirements excluded by EXCLUDED_REQUIREMENTS_ALL which should be included when
# building integration wheels for all architectures.
INCLUDED_REQUIREMENTS_WHEELS = {
"decora-wifi",
"evdev",
"pycups",
"python-gammu",
@@ -138,8 +136,8 @@ uuid==1000000000.0.0
# even newer versions seem to introduce new issues, it's useful for us to pin all these
# requirements so we can directly link HA versions to these library versions.
anyio==4.9.0
h11==0.14.0
httpcore==1.0.7
h11==0.16.0
httpcore==1.0.9
# Ensure we have a hyperframe version that works in Python 3.10
# 5.2.0 fixed a collections abc deprecation

View File

@@ -25,7 +25,7 @@ RUN --mount=from=ghcr.io/astral-sh/uv:0.7.1,source=/uv,target=/bin/uv \
-c /usr/src/homeassistant/homeassistant/package_constraints.txt \
-r /usr/src/homeassistant/requirements.txt \
stdlib-list==0.10.0 pipdeptree==2.26.1 tqdm==4.67.1 ruff==0.11.0 \
PyTurboJPEG==1.7.5 go2rtc-client==0.1.3b0 ha-ffmpeg==3.2.2 hassil==2.2.3 home-assistant-intents==2025.5.7 mutagen==1.47.0 pymicro-vad==1.0.1 pyspeex-noise==1.0.2
PyTurboJPEG==1.7.5 go2rtc-client==0.1.3b0 ha-ffmpeg==3.2.2 hassil==2.2.3 home-assistant-intents==2025.5.28 mutagen==1.47.0 pymicro-vad==1.0.1 pyspeex-noise==1.0.2
LABEL "name"="hassfest"
LABEL "maintainer"="Home Assistant <hello@home-assistant.io>"

View File

@@ -2,7 +2,7 @@
from unittest.mock import patch
from homeassistant.components.abode import DOMAIN as ABODE_DOMAIN
from homeassistant.components.abode import DOMAIN
from homeassistant.components.abode.const import CONF_POLLING
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
@@ -14,7 +14,7 @@ from tests.common import MockConfigEntry
async def setup_platform(hass: HomeAssistant, platform: str) -> MockConfigEntry:
"""Set up the Abode platform."""
mock_entry = MockConfigEntry(
domain=ABODE_DOMAIN,
domain=DOMAIN,
data={
CONF_USERNAME: "user@email.com",
CONF_PASSWORD: "password",
@@ -27,7 +27,7 @@ async def setup_platform(hass: HomeAssistant, platform: str) -> MockConfigEntry:
patch("homeassistant.components.abode.PLATFORMS", [platform]),
patch("jaraco.abode.event_controller.sio"),
):
assert await async_setup_component(hass, ABODE_DOMAIN, {})
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
return mock_entry

View File

@@ -2,7 +2,7 @@
from unittest.mock import patch
from homeassistant.components.abode.const import DOMAIN as ABODE_DOMAIN
from homeassistant.components.abode.const import DOMAIN
from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN, CameraState
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
@@ -35,7 +35,7 @@ async def test_capture_image(hass: HomeAssistant) -> None:
with patch("jaraco.abode.devices.camera.Camera.capture") as mock_capture:
await hass.services.async_call(
ABODE_DOMAIN,
DOMAIN,
"capture_image",
{ATTR_ENTITY_ID: "camera.test_cam"},
blocking=True,

View File

@@ -8,7 +8,7 @@ from jaraco.abode.exceptions import (
Exception as AbodeException,
)
from homeassistant.components.abode import DOMAIN as ABODE_DOMAIN, SERVICE_SETTINGS
from homeassistant.components.abode import DOMAIN, SERVICE_SETTINGS
from homeassistant.components.alarm_control_panel import DOMAIN as ALARM_DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_USERNAME
@@ -23,7 +23,7 @@ async def test_change_settings(hass: HomeAssistant) -> None:
with patch("jaraco.abode.client.Client.set_setting") as mock_set_setting:
await hass.services.async_call(
ABODE_DOMAIN,
DOMAIN,
SERVICE_SETTINGS,
{"setting": "confirm_snd", "value": "loud"},
blocking=True,

View File

@@ -2,10 +2,7 @@
from unittest.mock import patch
from homeassistant.components.abode import (
DOMAIN as ABODE_DOMAIN,
SERVICE_TRIGGER_AUTOMATION,
)
from homeassistant.components.abode import DOMAIN, SERVICE_TRIGGER_AUTOMATION
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
from homeassistant.const import (
ATTR_ENTITY_ID,
@@ -119,7 +116,7 @@ async def test_trigger_automation(hass: HomeAssistant) -> None:
with patch("jaraco.abode.automation.Automation.trigger") as mock:
await hass.services.async_call(
ABODE_DOMAIN,
DOMAIN,
SERVICE_TRIGGER_AUTOMATION,
{ATTR_ENTITY_ID: AUTOMATION_ID},
blocking=True,

View File

@@ -3,7 +3,7 @@
from datetime import timedelta
from unittest.mock import AsyncMock, patch
from homeassistant.components.advantage_air.const import DOMAIN as ADVANTAGE_AIR_DOMAIN
from homeassistant.components.advantage_air.const import DOMAIN
from homeassistant.components.advantage_air.sensor import (
ADVANTAGE_AIR_SERVICE_SET_TIME_TO,
ADVANTAGE_AIR_SET_COUNTDOWN_VALUE,
@@ -41,7 +41,7 @@ async def test_sensor_platform(
value = 20
await hass.services.async_call(
ADVANTAGE_AIR_DOMAIN,
DOMAIN,
ADVANTAGE_AIR_SERVICE_SET_TIME_TO,
{ATTR_ENTITY_ID: [entity_id], ADVANTAGE_AIR_SET_COUNTDOWN_VALUE: value},
blocking=True,
@@ -61,7 +61,7 @@ async def test_sensor_platform(
value = 0
await hass.services.async_call(
ADVANTAGE_AIR_DOMAIN,
DOMAIN,
ADVANTAGE_AIR_SERVICE_SET_TIME_TO,
{ATTR_ENTITY_ID: [entity_id], ADVANTAGE_AIR_SET_COUNTDOWN_VALUE: value},
blocking=True,

View File

@@ -4,7 +4,7 @@ from homeassistant.components.agent_dvr.const import DOMAIN, SERVER_URL
from homeassistant.const import CONF_HOST, CONF_PORT, CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture
from tests.common import MockConfigEntry, async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
CONF_DATA = {
@@ -34,12 +34,12 @@ async def init_integration(
aioclient_mock.get(
"http://example.local:8090/command.cgi?cmd=getStatus",
text=load_fixture("agent_dvr/status.json"),
text=await async_load_fixture(hass, "status.json", DOMAIN),
headers={"Content-Type": CONTENT_TYPE_JSON},
)
aioclient_mock.get(
"http://example.local:8090/command.cgi?cmd=getObjects",
text=load_fixture("agent_dvr/objects.json"),
text=await async_load_fixture(hass, "objects.json", DOMAIN),
headers={"Content-Type": CONTENT_TYPE_JSON},
)
entry = create_entry(hass)

View File

@@ -2,8 +2,7 @@
import pytest
from homeassistant.components.agent_dvr import config_flow
from homeassistant.components.agent_dvr.const import SERVER_URL
from homeassistant.components.agent_dvr.const import DOMAIN, SERVER_URL
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_HOST, CONF_PORT, CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant
@@ -11,7 +10,7 @@ from homeassistant.data_entry_flow import FlowResultType
from . import init_integration
from tests.common import load_fixture
from tests.common import async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
@@ -20,7 +19,7 @@ pytestmark = pytest.mark.usefixtures("mock_setup_entry")
async def test_show_user_form(hass: HomeAssistant) -> None:
"""Test that the user set up form is served."""
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": SOURCE_USER},
)
@@ -35,7 +34,7 @@ async def test_user_device_exists_abort(
await init_integration(hass, aioclient_mock)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "example.local", CONF_PORT: 8090},
)
@@ -51,7 +50,7 @@ async def test_connection_error(
aioclient_mock.get("http://example.local:8090/command.cgi?cmd=getStatus", text="")
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "example.local", CONF_PORT: 8090},
)
@@ -67,18 +66,18 @@ async def test_full_user_flow_implementation(
"""Test the full manual user flow from start to finish."""
aioclient_mock.get(
"http://example.local:8090/command.cgi?cmd=getStatus",
text=load_fixture("agent_dvr/status.json"),
text=await async_load_fixture(hass, "status.json", DOMAIN),
headers={"Content-Type": CONTENT_TYPE_JSON},
)
aioclient_mock.get(
"http://example.local:8090/command.cgi?cmd=getObjects",
text=load_fixture("agent_dvr/objects.json"),
text=await async_load_fixture(hass, "objects.json", DOMAIN),
headers={"Content-Type": CONTENT_TYPE_JSON},
)
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
DOMAIN,
context={"source": SOURCE_USER},
)
@@ -95,5 +94,5 @@ async def test_full_user_flow_implementation(
assert result["title"] == "DESKTOP"
assert result["type"] is FlowResultType.CREATE_ENTRY
entries = hass.config_entries.async_entries(config_flow.DOMAIN)
entries = hass.config_entries.async_entries(DOMAIN)
assert entries[0].unique_id == "c0715bba-c2d0-48ef-9e3e-bc81c9ea4447"

View File

@@ -20,7 +20,7 @@ from . import setup_integration
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_fixture,
async_load_fixture,
snapshot_platform,
)
@@ -81,7 +81,7 @@ async def test_cloud_creates_no_button(
assert len(hass.states.async_all()) == 0
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_local.json", DOMAIN)
await async_load_fixture(hass, "get_config_local.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))
@@ -91,7 +91,7 @@ async def test_cloud_creates_no_button(
assert len(hass.states.async_all()) == 2
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_cloud.json", DOMAIN)
await async_load_fixture(hass, "get_config_cloud.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))

View File

@@ -24,7 +24,7 @@ from . import setup_integration
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_fixture,
async_load_fixture,
snapshot_platform,
)
@@ -83,7 +83,7 @@ async def test_cloud_creates_no_number(
assert len(hass.states.async_all()) == 0
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_local.json", DOMAIN)
await async_load_fixture(hass, "get_config_local.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))
@@ -93,7 +93,7 @@ async def test_cloud_creates_no_number(
assert len(hass.states.async_all()) == 2
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_cloud.json", DOMAIN)
await async_load_fixture(hass, "get_config_cloud.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))

View File

@@ -23,7 +23,7 @@ from . import setup_integration
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_fixture,
async_load_fixture,
snapshot_platform,
)
@@ -77,7 +77,7 @@ async def test_cloud_creates_no_number(
assert len(hass.states.async_all()) == 1
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_local.json", DOMAIN)
await async_load_fixture(hass, "get_config_local.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))
@@ -87,7 +87,7 @@ async def test_cloud_creates_no_number(
assert len(hass.states.async_all()) == 7
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_cloud.json", DOMAIN)
await async_load_fixture(hass, "get_config_cloud.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))

View File

@@ -18,7 +18,7 @@ from . import setup_integration
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_fixture,
async_load_fixture,
snapshot_platform,
)
@@ -46,14 +46,14 @@ async def test_create_entities(
) -> None:
"""Test creating entities."""
mock_airgradient_client.get_current_measures.return_value = Measures.from_json(
load_fixture("measures_after_boot.json", DOMAIN)
await async_load_fixture(hass, "measures_after_boot.json", DOMAIN)
)
with patch("homeassistant.components.airgradient.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, mock_config_entry)
assert len(hass.states.async_all()) == 0
mock_airgradient_client.get_current_measures.return_value = Measures.from_json(
load_fixture("current_measures_indoor.json", DOMAIN)
await async_load_fixture(hass, "current_measures_indoor.json", DOMAIN)
)
freezer.tick(timedelta(minutes=1))
async_fire_time_changed(hass)

View File

@@ -25,7 +25,7 @@ from . import setup_integration
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_fixture,
async_load_fixture,
snapshot_platform,
)
@@ -83,7 +83,7 @@ async def test_cloud_creates_no_switch(
assert len(hass.states.async_all()) == 0
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_local.json", DOMAIN)
await async_load_fixture(hass, "get_config_local.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))
@@ -93,7 +93,7 @@ async def test_cloud_creates_no_switch(
assert len(hass.states.async_all()) == 1
mock_cloud_airgradient_client.get_config.return_value = Config.from_json(
load_fixture("get_config_cloud.json", DOMAIN)
await async_load_fixture(hass, "get_config_cloud.json", DOMAIN)
)
freezer.tick(timedelta(minutes=5))

View File

@@ -3,7 +3,7 @@
from homeassistant.components.airly.const import DOMAIN
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry, load_fixture
from tests.common import MockConfigEntry, async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
API_NEAREST_URL = "https://airapi.airly.eu/v2/measurements/nearest?lat=123.000000&lng=456.000000&maxDistanceKM=5.000000"
@@ -34,7 +34,9 @@ async def init_integration(
)
aioclient_mock.get(
API_POINT_URL, text=load_fixture("valid_station.json", DOMAIN), headers=HEADERS
API_POINT_URL,
text=await async_load_fixture(hass, "valid_station.json", DOMAIN),
headers=HEADERS,
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)

View File

@@ -12,7 +12,7 @@ from homeassistant.data_entry_flow import FlowResultType
from . import API_NEAREST_URL, API_POINT_URL
from tests.common import MockConfigEntry, load_fixture, patch
from tests.common import MockConfigEntry, async_load_fixture, patch
from tests.test_util.aiohttp import AiohttpClientMocker
CONFIG = {
@@ -55,7 +55,9 @@ async def test_invalid_location(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test that errors are shown when location is invalid."""
aioclient_mock.get(API_POINT_URL, text=load_fixture("no_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "no_station.json", DOMAIN)
)
aioclient_mock.get(
API_NEAREST_URL,
@@ -74,9 +76,13 @@ async def test_invalid_location_for_point_and_nearest(
) -> None:
"""Test an abort when the location is wrong for the point and nearest methods."""
aioclient_mock.get(API_POINT_URL, text=load_fixture("no_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "no_station.json", DOMAIN)
)
aioclient_mock.get(API_NEAREST_URL, text=load_fixture("no_station.json", "airly"))
aioclient_mock.get(
API_NEAREST_URL, text=await async_load_fixture(hass, "no_station.json", DOMAIN)
)
with patch("homeassistant.components.airly.async_setup_entry", return_value=True):
result = await hass.config_entries.flow.async_init(
@@ -91,7 +97,9 @@ async def test_duplicate_error(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test that errors are shown when duplicates are added."""
aioclient_mock.get(API_POINT_URL, text=load_fixture("valid_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "valid_station.json", DOMAIN)
)
MockConfigEntry(domain=DOMAIN, unique_id="123-456", data=CONFIG).add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
@@ -106,7 +114,9 @@ async def test_create_entry(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test that the user step works."""
aioclient_mock.get(API_POINT_URL, text=load_fixture("valid_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "valid_station.json", DOMAIN)
)
with patch("homeassistant.components.airly.async_setup_entry", return_value=True):
result = await hass.config_entries.flow.async_init(
@@ -126,10 +136,13 @@ async def test_create_entry_with_nearest_method(
) -> None:
"""Test that the user step works with nearest method."""
aioclient_mock.get(API_POINT_URL, text=load_fixture("no_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "no_station.json", DOMAIN)
)
aioclient_mock.get(
API_NEAREST_URL, text=load_fixture("valid_station.json", "airly")
API_NEAREST_URL,
text=await async_load_fixture(hass, "valid_station.json", DOMAIN),
)
with patch("homeassistant.components.airly.async_setup_entry", return_value=True):

View File

@@ -15,7 +15,7 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import API_POINT_URL, init_integration
from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture
from tests.common import MockConfigEntry, async_fire_time_changed, async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
@@ -69,7 +69,9 @@ async def test_config_without_unique_id(
},
)
aioclient_mock.get(API_POINT_URL, text=load_fixture("valid_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "valid_station.json", DOMAIN)
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
@@ -92,7 +94,9 @@ async def test_config_with_turned_off_station(
},
)
aioclient_mock.get(API_POINT_URL, text=load_fixture("no_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "no_station.json", DOMAIN)
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
@@ -124,7 +128,7 @@ async def test_update_interval(
aioclient_mock.get(
API_POINT_URL,
text=load_fixture("valid_station.json", "airly"),
text=await async_load_fixture(hass, "valid_station.json", DOMAIN),
headers=HEADERS,
)
entry.add_to_hass(hass)
@@ -159,7 +163,7 @@ async def test_update_interval(
aioclient_mock.get(
"https://airapi.airly.eu/v2/measurements/point?lat=66.660000&lng=111.110000",
text=load_fixture("valid_station.json", "airly"),
text=await async_load_fixture(hass, "valid_station.json", DOMAIN),
headers=HEADERS,
)
entry.add_to_hass(hass)
@@ -216,7 +220,9 @@ async def test_migrate_device_entry(
},
)
aioclient_mock.get(API_POINT_URL, text=load_fixture("valid_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "valid_station.json", DOMAIN)
)
config_entry.add_to_hass(hass)
device_entry = device_registry.async_get_or_create(

View File

@@ -7,6 +7,7 @@ from unittest.mock import patch
from airly.exceptions import AirlyError
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.airly.const import DOMAIN
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
@@ -15,7 +16,7 @@ from homeassistant.util.dt import utcnow
from . import API_POINT_URL, init_integration
from tests.common import async_fire_time_changed, load_fixture
from tests.common import async_fire_time_changed, async_load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
@@ -62,7 +63,9 @@ async def test_availability(
assert state.state == STATE_UNAVAILABLE
aioclient_mock.clear_requests()
aioclient_mock.get(API_POINT_URL, text=load_fixture("valid_station.json", "airly"))
aioclient_mock.get(
API_POINT_URL, text=await async_load_fixture(hass, "valid_station.json", DOMAIN)
)
future = utcnow() + timedelta(minutes=120)
async_fire_time_changed(hass, future)
await hass.async_block_till_done()

View File

@@ -1,8 +1,5 @@
"""The tests for Alarm control panel platforms."""
from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
@@ -13,7 +10,7 @@ async def help_async_setup_entry_init(
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(
config_entry, [ALARM_CONTROL_PANEL_DOMAIN]
config_entry, [Platform.ALARM_CONTROL_PANEL]
)
return True

View File

@@ -6,12 +6,13 @@ from unittest.mock import MagicMock, patch
import pytest
from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
DOMAIN,
AlarmControlPanelEntity,
AlarmControlPanelEntityFeature,
)
from homeassistant.components.alarm_control_panel.const import CodeFormat
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er, frame
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -172,7 +173,7 @@ async def setup_alarm_control_panel_platform_test_entity(
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(
config_entry, [ALARM_CONTROL_PANEL_DOMAIN]
config_entry, [Platform.ALARM_CONTROL_PANEL]
)
return True
@@ -201,7 +202,7 @@ async def setup_alarm_control_panel_platform_test_entity(
mock_platform(
hass,
f"{TEST_DOMAIN}.{ALARM_CONTROL_PANEL_DOMAIN}",
f"{TEST_DOMAIN}.{DOMAIN}",
MockPlatform(async_setup_entry=async_setup_entry_platform),
)

View File

@@ -6,7 +6,7 @@ import pytest
from homeassistant.components import alarm_control_panel
from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
DOMAIN,
AlarmControlPanelEntityFeature,
CodeFormat,
)
@@ -280,9 +280,7 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_state_prop
),
built_in=False,
)
setup_test_component_platform(
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
)
setup_test_component_platform(hass, DOMAIN, [entity], from_config_entry=True)
assert await hass.config_entries.async_setup(config_entry.entry_id)
state = hass.states.get(entity.entity_id)
@@ -343,9 +341,7 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_attr_state
),
built_in=False,
)
setup_test_component_platform(
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
)
setup_test_component_platform(hass, DOMAIN, [entity], from_config_entry=True)
assert await hass.config_entries.async_setup(config_entry.entry_id)
state = hass.states.get(entity.entity_id)
@@ -426,9 +422,7 @@ async def test_alarm_control_panel_deprecated_state_does_not_break_state(
),
built_in=False,
)
setup_test_component_platform(
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
)
setup_test_component_platform(hass, DOMAIN, [entity], from_config_entry=True)
assert await hass.config_entries.async_setup(config_entry.entry_id)
state = hass.states.get(entity.entity_id)

View File

@@ -16,6 +16,7 @@ from homeassistant.components.assist_pipeline.select import (
)
from homeassistant.components.assist_pipeline.vad import VadSensitivity
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceInfo
@@ -53,7 +54,9 @@ async def init_select(hass: HomeAssistant, init_components) -> ConfigEntry:
domain="assist_pipeline", state=ConfigEntryState.LOADED
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_forward_entry_setups(config_entry, ["select"])
await hass.config_entries.async_forward_entry_setups(
config_entry, [Platform.SELECT]
)
return config_entry
@@ -160,8 +163,12 @@ async def test_select_entity_changing_pipelines(
assert state.state == pipeline_2.name
# Reload config entry to test selected option persists
assert await hass.config_entries.async_forward_entry_unload(config_entry, "select")
await hass.config_entries.async_forward_entry_setups(config_entry, ["select"])
assert await hass.config_entries.async_forward_entry_unload(
config_entry, Platform.SELECT
)
await hass.config_entries.async_forward_entry_setups(
config_entry, [Platform.SELECT]
)
state = hass.states.get("select.assist_pipeline_test_prefix_pipeline")
assert state is not None
@@ -208,8 +215,12 @@ async def test_select_entity_changing_vad_sensitivity(
assert state.state == VadSensitivity.AGGRESSIVE.value
# Reload config entry to test selected option persists
assert await hass.config_entries.async_forward_entry_unload(config_entry, "select")
await hass.config_entries.async_forward_entry_setups(config_entry, ["select"])
assert await hass.config_entries.async_forward_entry_unload(
config_entry, Platform.SELECT
)
await hass.config_entries.async_forward_entry_setups(
config_entry, [Platform.SELECT]
)
state = hass.states.get("select.assist_pipeline_test_vad_sensitivity")
assert state is not None

View File

@@ -7,7 +7,7 @@ import pytest
from homeassistant.components.assist_pipeline import PipelineEvent
from homeassistant.components.assist_satellite import (
DOMAIN as AS_DOMAIN,
DOMAIN,
AssistSatelliteAnnouncement,
AssistSatelliteConfiguration,
AssistSatelliteEntity,
@@ -15,6 +15,7 @@ from homeassistant.components.assist_satellite import (
AssistSatelliteWakeWord,
)
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.setup import async_setup_component
@@ -144,14 +145,18 @@ async def init_components(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(config_entry, [AS_DOMAIN])
await hass.config_entries.async_forward_entry_setups(
config_entry, [Platform.ASSIST_SATELLITE]
)
return True
async def async_unload_entry_init(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Unload test config entry."""
await hass.config_entries.async_forward_entry_unload(config_entry, AS_DOMAIN)
await hass.config_entries.async_forward_entry_unload(
config_entry, Platform.ASSIST_SATELLITE
)
return True
mock_integration(
@@ -163,7 +168,7 @@ async def init_components(
),
)
setup_test_component_platform(
hass, AS_DOMAIN, [entity, entity2, entity_no_features], from_config_entry=True
hass, DOMAIN, [entity, entity2, entity_no_features], from_config_entry=True
)
mock_platform(hass, f"{TEST_DOMAIN}.config_flow", Mock())

View File

@@ -3,10 +3,7 @@
from typing import Any
from unittest.mock import patch
from homeassistant.components.aussie_broadband.const import (
CONF_SERVICES,
DOMAIN as AUSSIE_BROADBAND_DOMAIN,
)
from homeassistant.components.aussie_broadband.const import CONF_SERVICES, DOMAIN
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import UNDEFINED, UndefinedType
@@ -49,7 +46,7 @@ async def setup_platform(
):
"""Set up the Aussie Broadband platform."""
mock_entry = MockConfigEntry(
domain=AUSSIE_BROADBAND_DOMAIN,
domain=DOMAIN,
data=FAKE_DATA,
options={
CONF_SERVICES: ["12345678", "87654321", "23456789", "98765432"],

View File

@@ -12,7 +12,7 @@ from axis.rtsp import Signal, State
import pytest
import respx
from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
from homeassistant.components.axis.const import DOMAIN
from homeassistant.const import (
CONF_HOST,
CONF_MODEL,
@@ -91,7 +91,7 @@ def fixture_config_entry(
) -> MockConfigEntry:
"""Define a config entry fixture."""
return MockConfigEntry(
domain=AXIS_DOMAIN,
domain=DOMAIN,
entry_id="676abe5b73621446e6550a2e86ffe3dd",
unique_id=FORMATTED_MAC,
data=config_entry_data,

View File

@@ -12,7 +12,7 @@ from homeassistant.components.axis.const import (
CONF_VIDEO_SOURCE,
DEFAULT_STREAM_PROFILE,
DEFAULT_VIDEO_SOURCE,
DOMAIN as AXIS_DOMAIN,
DOMAIN,
)
from homeassistant.config_entries import (
SOURCE_DHCP,
@@ -47,7 +47,7 @@ DHCP_FORMATTED_MAC = dr.format_mac(MAC).replace(":", "")
async def test_flow_manual_configuration(hass: HomeAssistant) -> None:
"""Test that config flow works."""
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, context={"source": SOURCE_USER}
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
@@ -86,7 +86,7 @@ async def test_manual_configuration_duplicate_fails(
assert config_entry_setup.data[CONF_HOST] == "1.2.3.4"
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, context={"source": SOURCE_USER}
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
@@ -122,7 +122,7 @@ async def test_flow_fails_on_api(
) -> None:
"""Test that config flow fails on faulty credentials."""
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, context={"source": SOURCE_USER}
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
@@ -152,18 +152,18 @@ async def test_flow_create_entry_multiple_existing_entries_of_same_model(
) -> None:
"""Test that create entry can generate a name with other entries."""
entry = MockConfigEntry(
domain=AXIS_DOMAIN,
domain=DOMAIN,
data={CONF_NAME: "M1065-LW 0", CONF_MODEL: "M1065-LW"},
)
entry.add_to_hass(hass)
entry2 = MockConfigEntry(
domain=AXIS_DOMAIN,
domain=DOMAIN,
data={CONF_NAME: "M1065-LW 1", CONF_MODEL: "M1065-LW"},
)
entry2.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, context={"source": SOURCE_USER}
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
@@ -337,7 +337,7 @@ async def test_discovery_flow(
) -> None:
"""Test the different discovery flows for new devices work."""
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, data=discovery_info, context={"source": source}
DOMAIN, data=discovery_info, context={"source": source}
)
assert result["type"] is FlowResultType.FORM
@@ -420,7 +420,7 @@ async def test_discovered_device_already_configured(
assert config_entry_setup.data[CONF_HOST] == DEFAULT_HOST
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, data=discovery_info, context={"source": source}
DOMAIN, data=discovery_info, context={"source": source}
)
assert result["type"] is FlowResultType.ABORT
@@ -488,7 +488,7 @@ async def test_discovery_flow_updated_configuration(
mock_requests("2.3.4.5")
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, data=discovery_info, context={"source": source}
DOMAIN, data=discovery_info, context={"source": source}
)
await hass.async_block_till_done()
@@ -546,7 +546,7 @@ async def test_discovery_flow_ignore_non_axis_device(
) -> None:
"""Test that discovery flow ignores devices with non Axis OUI."""
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, data=discovery_info, context={"source": source}
DOMAIN, data=discovery_info, context={"source": source}
)
assert result["type"] is FlowResultType.ABORT
@@ -595,7 +595,7 @@ async def test_discovery_flow_ignore_link_local_address(
) -> None:
"""Test that discovery flow ignores devices with link local addresses."""
result = await hass.config_entries.flow.async_init(
AXIS_DOMAIN, data=discovery_info, context={"source": source}
DOMAIN, data=discovery_info, context={"source": source}
)
assert result["type"] is FlowResultType.ABORT

View File

@@ -12,7 +12,7 @@ import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components import axis
from homeassistant.components.axis.const import DOMAIN as AXIS_DOMAIN
from homeassistant.components.axis.const import DOMAIN
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
from homeassistant.config_entries import SOURCE_ZEROCONF, ConfigEntryState
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
@@ -43,7 +43,7 @@ async def test_device_registry_entry(
) -> None:
"""Successful setup."""
device_entry = device_registry.async_get_device(
identifiers={(AXIS_DOMAIN, config_entry_setup.unique_id)}
identifiers={(DOMAIN, config_entry_setup.unique_id)}
)
assert device_entry == snapshot
@@ -93,7 +93,7 @@ async def test_update_address(
mock_requests("2.3.4.5")
await hass.config_entries.flow.async_init(
AXIS_DOMAIN,
DOMAIN,
data=ZeroconfServiceInfo(
ip_address=ip_address("2.3.4.5"),
ip_addresses=[ip_address("2.3.4.5")],

View File

@@ -2,7 +2,7 @@
from unittest.mock import MagicMock
from homeassistant.components.balboa.const import DOMAIN as BALBOA_DOMAIN
from homeassistant.components.balboa.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
@@ -24,7 +24,7 @@ async def test_setup_entry(
async def test_setup_entry_fails(hass: HomeAssistant, client: MagicMock) -> None:
"""Validate that setup entry also configure the client."""
config_entry = MockConfigEntry(
domain=BALBOA_DOMAIN,
domain=DOMAIN,
data={
CONF_HOST: TEST_HOST,
},

View File

@@ -7,7 +7,7 @@ import pytest
from homeassistant.components import binary_sensor
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory
from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -62,7 +62,7 @@ async def test_name(hass: HomeAssistant) -> None:
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(
config_entry, [binary_sensor.DOMAIN]
config_entry, [Platform.BINARY_SENSOR]
)
return True
@@ -142,7 +142,7 @@ async def test_entity_category_config_raises_error(
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(
config_entry, [binary_sensor.DOMAIN]
config_entry, [Platform.BINARY_SENSOR]
)
return True

View File

@@ -6,11 +6,11 @@ from pathlib import Path
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.blueprint import importer
from homeassistant.components.blueprint import DOMAIN, importer
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from tests.common import load_fixture
from tests.common import async_load_fixture, load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
@@ -161,7 +161,7 @@ async def test_fetch_blueprint_from_github_gist_url(
"""Test fetching blueprint from url."""
aioclient_mock.get(
"https://api.github.com/gists/e717ce85dd0d2f1bdcdfc884ea25a344",
text=load_fixture("blueprint/github_gist.json"),
text=await async_load_fixture(hass, "github_gist.json", DOMAIN),
)
url = "https://gist.github.com/balloob/e717ce85dd0d2f1bdcdfc884ea25a344"

View File

@@ -9,7 +9,7 @@ import pytest
from syrupy.assertion import SnapshotAssertion
from syrupy.filters import props
from homeassistant.components.bluesound import DOMAIN as BLUESOUND_DOMAIN
from homeassistant.components.bluesound import DOMAIN
from homeassistant.components.bluesound.const import ATTR_MASTER
from homeassistant.components.bluesound.media_player import (
SERVICE_CLEAR_TIMER,
@@ -230,7 +230,7 @@ async def test_set_sleep_timer(
) -> None:
"""Test the set sleep timer action."""
await hass.services.async_call(
BLUESOUND_DOMAIN,
DOMAIN,
SERVICE_SET_TIMER,
{ATTR_ENTITY_ID: "media_player.player_name1111"},
blocking=True,
@@ -247,7 +247,7 @@ async def test_clear_sleep_timer(
player_mocks.player_data.player.sleep_timer.side_effect = [15, 30, 45, 60, 90, 0]
await hass.services.async_call(
BLUESOUND_DOMAIN,
DOMAIN,
SERVICE_CLEAR_TIMER,
{ATTR_ENTITY_ID: "media_player.player_name1111"},
blocking=True,
@@ -262,7 +262,7 @@ async def test_join_cannot_join_to_self(
"""Test that joining to self is not allowed."""
with pytest.raises(ServiceValidationError, match="Cannot join player to itself"):
await hass.services.async_call(
BLUESOUND_DOMAIN,
DOMAIN,
SERVICE_JOIN,
{
ATTR_ENTITY_ID: "media_player.player_name1111",
@@ -280,7 +280,7 @@ async def test_join(
) -> None:
"""Test the join action."""
await hass.services.async_call(
BLUESOUND_DOMAIN,
DOMAIN,
SERVICE_JOIN,
{
ATTR_ENTITY_ID: "media_player.player_name1111",
@@ -311,7 +311,7 @@ async def test_unjoin(
await hass.async_block_till_done()
await hass.services.async_call(
BLUESOUND_DOMAIN,
DOMAIN,
"unjoin",
{ATTR_ENTITY_ID: "media_player.player_name1111"},
blocking=True,

View File

@@ -41,7 +41,7 @@ from . import (
patch_bluetooth_time,
)
from tests.common import MockConfigEntry, async_fire_time_changed, load_fixture
from tests.common import MockConfigEntry, async_fire_time_changed, async_load_fixture
@pytest.mark.parametrize("name_2", [None, "w"])
@@ -313,7 +313,7 @@ async def test_restore_history_remote_adapter(
"""Test we can restore history for a remote adapter."""
data = hass_storage[storage.REMOTE_SCANNER_STORAGE_KEY] = json_loads(
load_fixture("bluetooth.remote_scanners", bluetooth.DOMAIN)
await async_load_fixture(hass, "bluetooth.remote_scanners", bluetooth.DOMAIN)
)
now = time.time()
timestamps = data["data"]["atom-bluetooth-proxy-ceaac4"][

View File

@@ -63,7 +63,7 @@ from tests.common import (
MockModule,
async_call_logger_set_level,
async_fire_time_changed,
load_fixture,
async_load_fixture,
mock_integration,
)
@@ -453,7 +453,7 @@ async def test_restore_history_from_dbus_and_remote_adapters(
address = "AA:BB:CC:CC:CC:FF"
data = hass_storage[storage.REMOTE_SCANNER_STORAGE_KEY] = json_loads(
load_fixture("bluetooth.remote_scanners", bluetooth.DOMAIN)
await async_load_fixture(hass, "bluetooth.remote_scanners", bluetooth.DOMAIN)
)
now = time.time()
timestamps = data["data"]["atom-bluetooth-proxy-ceaac4"][
@@ -495,7 +495,9 @@ async def test_restore_history_from_dbus_and_corrupted_remote_adapters(
address = "AA:BB:CC:CC:CC:FF"
data = hass_storage[storage.REMOTE_SCANNER_STORAGE_KEY] = json_loads(
load_fixture("bluetooth.remote_scanners.corrupt", bluetooth.DOMAIN)
await async_load_fixture(
hass, "bluetooth.remote_scanners.corrupt", bluetooth.DOMAIN
)
)
now = time.time()
timestamps = data["data"]["atom-bluetooth-proxy-ceaac4"][

View File

@@ -13,7 +13,7 @@ from homeassistant.components.bmw_connected_drive.const import (
CONF_GCID,
CONF_READ_ONLY,
CONF_REFRESH_TOKEN,
DOMAIN as BMW_DOMAIN,
DOMAIN,
)
from homeassistant.const import CONF_PASSWORD, CONF_REGION, CONF_USERNAME
from homeassistant.core import HomeAssistant
@@ -34,7 +34,7 @@ FIXTURE_GCID = "DUMMY"
FIXTURE_CONFIG_ENTRY = {
"entry_id": "1",
"domain": BMW_DOMAIN,
"domain": DOMAIN,
"title": FIXTURE_USER_INPUT[CONF_USERNAME],
"data": {
CONF_USERNAME: FIXTURE_USER_INPUT[CONF_USERNAME],

View File

@@ -11,7 +11,7 @@ from bimmer_connected.models import (
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.bmw_connected_drive import DOMAIN as BMW_DOMAIN
from homeassistant.components.bmw_connected_drive import DOMAIN
from homeassistant.components.bmw_connected_drive.const import (
CONF_REFRESH_TOKEN,
SCAN_INTERVALS,
@@ -140,7 +140,7 @@ async def test_auth_failed_as_update_failed(
# Verify that no issues are raised and no reauth flow is initialized
assert len(issue_registry.issues) == 0
assert len(hass.config_entries.flow.async_progress_by_handler(BMW_DOMAIN)) == 0
assert len(hass.config_entries.flow.async_progress_by_handler(DOMAIN)) == 0
@pytest.mark.usefixtures("bmw_fixture")
@@ -190,13 +190,13 @@ async def test_auth_failed_init_reauth(
reauth_issue = issue_registry.async_get_issue(
HOMEASSISTANT_DOMAIN,
f"config_entry_reauth_{BMW_DOMAIN}_{config_entry.entry_id}",
f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}",
)
assert reauth_issue.active is True
# Check if reauth flow is initialized correctly
flow = hass.config_entries.flow.async_get(reauth_issue.data["flow_id"])
assert flow["handler"] == BMW_DOMAIN
assert flow["handler"] == DOMAIN
assert flow["context"]["source"] == "reauth"
assert flow["context"]["unique_id"] == config_entry.unique_id
@@ -233,12 +233,12 @@ async def test_captcha_reauth(
reauth_issue = issue_registry.async_get_issue(
HOMEASSISTANT_DOMAIN,
f"config_entry_reauth_{BMW_DOMAIN}_{config_entry.entry_id}",
f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}",
)
assert reauth_issue.active is True
# Check if reauth flow is initialized correctly
flow = hass.config_entries.flow.async_get(reauth_issue.data["flow_id"])
assert flow["handler"] == BMW_DOMAIN
assert flow["handler"] == DOMAIN
assert flow["context"]["source"] == "reauth"
assert flow["context"]["unique_id"] == config_entry.unique_id

View File

@@ -6,10 +6,7 @@ from unittest.mock import patch
import pytest
from homeassistant.components.bmw_connected_drive import DEFAULT_OPTIONS
from homeassistant.components.bmw_connected_drive.const import (
CONF_READ_ONLY,
DOMAIN as BMW_DOMAIN,
)
from homeassistant.components.bmw_connected_drive.const import CONF_READ_ONLY, DOMAIN
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
@@ -82,7 +79,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None:
(
{
"domain": SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-charging_level_hv",
"suggested_object_id": f"{VEHICLE_NAME} charging_level_hv",
"disabled_by": None,
@@ -93,7 +90,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None:
(
{
"domain": SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-remaining_range_total",
"suggested_object_id": f"{VEHICLE_NAME} remaining_range_total",
"disabled_by": None,
@@ -104,7 +101,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None:
(
{
"domain": SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-mileage",
"suggested_object_id": f"{VEHICLE_NAME} mileage",
"disabled_by": None,
@@ -115,7 +112,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None:
(
{
"domain": SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-charging_status",
"suggested_object_id": f"{VEHICLE_NAME} Charging Status",
"disabled_by": None,
@@ -126,7 +123,7 @@ async def test_migrate_options_from_data(hass: HomeAssistant) -> None:
(
{
"domain": BINARY_SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-charging_status",
"suggested_object_id": f"{VEHICLE_NAME} Charging Status",
"disabled_by": None,
@@ -173,7 +170,7 @@ async def test_migrate_unique_ids(
(
{
"domain": SENSOR_DOMAIN,
"platform": BMW_DOMAIN,
"platform": DOMAIN,
"unique_id": f"{VIN}-charging_level_hv",
"suggested_object_id": f"{VEHICLE_NAME} charging_level_hv",
"disabled_by": None,
@@ -198,7 +195,7 @@ async def test_dont_migrate_unique_ids(
# create existing entry with new_unique_id
existing_entity = entity_registry.async_get_or_create(
SENSOR_DOMAIN,
BMW_DOMAIN,
DOMAIN,
unique_id=f"{VIN}-fuel_and_battery.remaining_battery_percent",
suggested_object_id=f"{VEHICLE_NAME} fuel_and_battery.remaining_battery_percent",
config_entry=mock_config_entry,
@@ -241,7 +238,7 @@ async def test_remove_stale_devices(
device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={(BMW_DOMAIN, "stale_device_id")},
identifiers={(DOMAIN, "stale_device_id")},
)
device_entries = dr.async_entries_for_config_entry(
device_registry, mock_config_entry.entry_id
@@ -249,7 +246,7 @@ async def test_remove_stale_devices(
assert len(device_entries) == 1
device_entry = device_entries[0]
assert device_entry.identifiers == {(BMW_DOMAIN, "stale_device_id")}
assert device_entry.identifiers == {(DOMAIN, "stale_device_id")}
assert await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
@@ -261,6 +258,4 @@ async def test_remove_stale_devices(
# Check that the test vehicles are still available but not the stale device
assert len(device_entries) > 0
remaining_device_identifiers = set().union(*(d.identifiers for d in device_entries))
assert not {(BMW_DOMAIN, "stale_device_id")}.intersection(
remaining_device_identifiers
)
assert not {(DOMAIN, "stale_device_id")}.intersection(remaining_device_identifiers)

View File

@@ -8,7 +8,7 @@ import pytest
import respx
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.bmw_connected_drive import DOMAIN as BMW_DOMAIN
from homeassistant.components.bmw_connected_drive import DOMAIN
from homeassistant.components.bmw_connected_drive.select import SELECT_TYPES
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
@@ -182,9 +182,9 @@ async def test_entity_option_translations(
# Setup component to load translations
assert await setup_mocked_integration(hass)
prefix = f"component.{BMW_DOMAIN}.entity.{Platform.SELECT.value}"
prefix = f"component.{DOMAIN}.entity.{Platform.SELECT.value}"
translations = await async_get_translations(hass, "en", "entity", [BMW_DOMAIN])
translations = await async_get_translations(hass, "en", "entity", [DOMAIN])
translation_states = {
k for k in translations if k.startswith(prefix) and ".state." in k
}

View File

@@ -8,7 +8,7 @@ from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.bmw_connected_drive import DOMAIN as BMW_DOMAIN
from homeassistant.components.bmw_connected_drive import DOMAIN
from homeassistant.components.bmw_connected_drive.const import SCAN_INTERVALS
from homeassistant.components.bmw_connected_drive.sensor import SENSOR_TYPES
from homeassistant.components.sensor import SensorDeviceClass
@@ -96,9 +96,9 @@ async def test_entity_option_translations(
# Setup component to load translations
assert await setup_mocked_integration(hass)
prefix = f"component.{BMW_DOMAIN}.entity.{Platform.SENSOR.value}"
prefix = f"component.{DOMAIN}.entity.{Platform.SENSOR.value}"
translations = await async_get_translations(hass, "en", "entity", [BMW_DOMAIN])
translations = await async_get_translations(hass, "en", "entity", [DOMAIN])
translation_states = {
k for k in translations if k.startswith(prefix) and ".state." in k
}

View File

@@ -11,7 +11,7 @@ from aiohttp.client_exceptions import ClientResponseError
from bond_async import DeviceType
from homeassistant import core
from homeassistant.components.bond.const import DOMAIN as BOND_DOMAIN
from homeassistant.components.bond.const import DOMAIN
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST, STATE_UNAVAILABLE
from homeassistant.setup import async_setup_component
from homeassistant.util import utcnow
@@ -77,7 +77,7 @@ async def setup_platform(
):
"""Set up the specified Bond platform."""
mock_entry = MockConfigEntry(
domain=BOND_DOMAIN,
domain=DOMAIN,
data={CONF_HOST: "some host", CONF_ACCESS_TOKEN: "test-token"},
)
mock_entry.add_to_hass(hass)
@@ -93,7 +93,7 @@ async def setup_platform(
patch_bond_device_properties(return_value=props),
patch_bond_device_state(return_value=state),
):
assert await async_setup_component(hass, BOND_DOMAIN, {})
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
return mock_entry

View File

@@ -11,7 +11,7 @@ import pytest
from homeassistant import core
from homeassistant.components import fan
from homeassistant.components.bond.const import (
DOMAIN as BOND_DOMAIN,
DOMAIN,
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
)
from homeassistant.components.bond.fan import PRESET_MODE_BREEZE
@@ -367,7 +367,7 @@ async def test_set_speed_belief_speed_zero(hass: HomeAssistant) -> None:
with patch_bond_action() as mock_action, patch_bond_device_state():
await hass.services.async_call(
BOND_DOMAIN,
DOMAIN,
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
{ATTR_ENTITY_ID: "fan.name_1", "speed": 0},
blocking=True,
@@ -391,7 +391,7 @@ async def test_set_speed_belief_speed_api_error(hass: HomeAssistant) -> None:
patch_bond_device_state(),
):
await hass.services.async_call(
BOND_DOMAIN,
DOMAIN,
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
{ATTR_ENTITY_ID: "fan.name_1", "speed": 100},
blocking=True,
@@ -406,7 +406,7 @@ async def test_set_speed_belief_speed_100(hass: HomeAssistant) -> None:
with patch_bond_action() as mock_action, patch_bond_device_state():
await hass.services.async_call(
BOND_DOMAIN,
DOMAIN,
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
{ATTR_ENTITY_ID: "fan.name_1", "speed": 100},
blocking=True,

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