forked from home-assistant/core
Merge branch 'dev' into fix-microsign-alt1
This commit is contained in:
6
homeassistant/brands/shelly.json
Normal file
6
homeassistant/brands/shelly.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"domain": "shelly",
|
||||
"name": "shelly",
|
||||
"integrations": ["shelly"],
|
||||
"iot_standards": ["zwave"]
|
||||
}
|
@@ -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
|
||||
|
36
homeassistant/components/airthings/coordinator.py
Normal file
36
homeassistant/components/airthings/coordinator.py
Normal 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
|
@@ -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:
|
||||
|
@@ -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",
|
||||
|
@@ -7,5 +7,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["pyaprilaire"],
|
||||
"requirements": ["pyaprilaire==0.9.0"]
|
||||
"requirements": ["pyaprilaire==0.9.1"]
|
||||
}
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -1 +1,3 @@
|
||||
"""The decora component."""
|
||||
|
||||
DOMAIN = "decora"
|
||||
|
@@ -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 = {}
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -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."]
|
||||
}
|
||||
|
@@ -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."
|
||||
|
@@ -8,5 +8,5 @@
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aioimmich"],
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["aioimmich==0.6.0"]
|
||||
"requirements": ["aioimmich==0.7.0"]
|
||||
}
|
||||
|
@@ -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."""
|
||||
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")
|
||||
try:
|
||||
identifier = ImmichMediaSourceIdentifier(item.identifier)
|
||||
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}")
|
||||
|
@@ -7,5 +7,5 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pyiskra"],
|
||||
"requirements": ["pyiskra==0.1.15"]
|
||||
"requirements": ["pyiskra==0.1.19"]
|
||||
}
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -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()
|
||||
|
@@ -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__)
|
||||
|
||||
|
@@ -37,5 +37,5 @@
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["pylamarzocco"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["pylamarzocco==2.0.7"]
|
||||
"requirements": ["pylamarzocco==2.0.8"]
|
||||
}
|
||||
|
@@ -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."]
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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(
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -15,5 +15,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["pyprobeplus==1.0.0"]
|
||||
"requirements": ["pyprobeplus==1.0.1"]
|
||||
}
|
||||
|
@@ -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"
|
||||
]
|
||||
|
@@ -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(
|
||||
|
@@ -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"
|
||||
},
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -910,6 +910,9 @@
|
||||
"auto_focus": {
|
||||
"name": "Auto focus"
|
||||
},
|
||||
"hardwired_chime_enabled": {
|
||||
"name": "Hardwired chime enabled"
|
||||
},
|
||||
"guard_return": {
|
||||
"name": "Guard return"
|
||||
},
|
||||
|
@@ -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 = (
|
||||
|
@@ -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,
|
||||
|
@@ -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."
|
||||
|
@@ -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
|
||||
|
@@ -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):
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -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] = {}
|
||||
|
@@ -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")
|
||||
|
@@ -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
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -8,5 +8,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiotedee"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["aiotedee==0.2.20"]
|
||||
"requirements": ["aiotedee==0.2.23"]
|
||||
}
|
||||
|
@@ -1 +1,4 @@
|
||||
"""The tensorflow component."""
|
||||
|
||||
DOMAIN = "tensorflow"
|
||||
CONF_GRAPH = "graph"
|
||||
|
@@ -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(
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -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,
|
||||
),
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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)},
|
||||
|
@@ -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)."""
|
||||
|
348
homeassistant/generated/dhcp.py
generated
348
homeassistant/generated/dhcp.py
generated
@@ -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",
|
||||
|
@@ -5867,10 +5867,18 @@
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"shelly": {
|
||||
"name": "Shelly",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
"name": "shelly",
|
||||
"integrations": {
|
||||
"shelly": {
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push",
|
||||
"name": "Shelly"
|
||||
}
|
||||
},
|
||||
"iot_standards": [
|
||||
"zwave"
|
||||
]
|
||||
},
|
||||
"shodan": {
|
||||
"name": "Shodan",
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
|
@@ -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
6
requirements.txt
generated
@@ -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
34
requirements_all.txt
generated
@@ -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
|
||||
|
53
requirements_test_all.txt
generated
53
requirements_test_all.txt
generated
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
2
script/hassfest/docker/Dockerfile
generated
2
script/hassfest/docker/Dockerfile
generated
@@ -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>"
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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)
|
||||
|
@@ -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))
|
||||
|
@@ -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)
|
||||
|
@@ -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):
|
||||
|
@@ -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(
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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),
|
||||
)
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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())
|
||||
|
||||
|
@@ -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"],
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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")],
|
||||
|
@@ -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,
|
||||
},
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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"
|
||||
|
@@ -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,
|
||||
|
@@ -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"][
|
||||
|
@@ -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"][
|
||||
|
@@ -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],
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
Reference in New Issue
Block a user