mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
2025.4.4 (#143653)
This commit is contained in:
commit
360bffa3a9
@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/chacon_dio",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["dio_chacon_api"],
|
||||
"requirements": ["dio-chacon-wifi-api==1.2.1"]
|
||||
"requirements": ["dio-chacon-wifi-api==1.2.2"]
|
||||
}
|
||||
|
@ -241,9 +241,7 @@ class HomeConnectCoordinator(
|
||||
appliance_data = await self._get_appliance_data(
|
||||
appliance_info, self.data.get(appliance_info.ha_id)
|
||||
)
|
||||
if event_message_ha_id in self.data:
|
||||
self.data[event_message_ha_id].update(appliance_data)
|
||||
else:
|
||||
if event_message_ha_id not in self.data:
|
||||
self.data[event_message_ha_id] = appliance_data
|
||||
for listener, context in self._special_listeners.values():
|
||||
if (
|
||||
|
@ -17,7 +17,6 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .common import setup_home_connect_entry
|
||||
from .const import (
|
||||
APPLIANCES_WITH_PROGRAMS,
|
||||
AVAILABLE_MAPS_ENUM,
|
||||
BEAN_AMOUNT_OPTIONS,
|
||||
BEAN_CONTAINER_OPTIONS,
|
||||
@ -313,7 +312,7 @@ def _get_entities_for_appliance(
|
||||
HomeConnectProgramSelectEntity(entry.runtime_data, appliance, desc)
|
||||
for desc in PROGRAM_SELECT_ENTITY_DESCRIPTIONS
|
||||
]
|
||||
if appliance.info.type in APPLIANCES_WITH_PROGRAMS
|
||||
if appliance.programs
|
||||
else []
|
||||
),
|
||||
*[
|
||||
|
@ -14,6 +14,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiohomekit", "commentjson"],
|
||||
"requirements": ["aiohomekit==3.2.13"],
|
||||
"requirements": ["aiohomekit==3.2.14"],
|
||||
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."]
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
@ -120,6 +121,8 @@ SERVICE_PLAY_PRESET_SCHEMA = cv.make_entity_service_schema(
|
||||
)
|
||||
|
||||
RETRY_POLL_MAXIMUM = 3
|
||||
SCAN_INTERVAL = timedelta(seconds=5)
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
|
@ -40,7 +40,7 @@ ATTR_NEXT_RAIN_DT_REF = "forecast_time_ref"
|
||||
|
||||
|
||||
CONDITION_CLASSES: dict[str, list[str]] = {
|
||||
ATTR_CONDITION_CLEAR_NIGHT: ["Nuit Claire", "Nuit claire"],
|
||||
ATTR_CONDITION_CLEAR_NIGHT: ["Nuit Claire", "Nuit claire", "Ciel clair"],
|
||||
ATTR_CONDITION_CLOUDY: ["Très nuageux", "Couvert"],
|
||||
ATTR_CONDITION_FOG: [
|
||||
"Brume ou bancs de brouillard",
|
||||
@ -48,9 +48,10 @@ CONDITION_CLASSES: dict[str, list[str]] = {
|
||||
"Brouillard",
|
||||
"Brouillard givrant",
|
||||
"Bancs de Brouillard",
|
||||
"Brouillard dense",
|
||||
],
|
||||
ATTR_CONDITION_HAIL: ["Risque de grêle", "Risque de grèle"],
|
||||
ATTR_CONDITION_LIGHTNING: ["Risque d'orages", "Orages"],
|
||||
ATTR_CONDITION_LIGHTNING: ["Risque d'orages", "Orages", "Orage avec grêle"],
|
||||
ATTR_CONDITION_LIGHTNING_RAINY: [
|
||||
"Pluie orageuses",
|
||||
"Pluies orageuses",
|
||||
@ -62,6 +63,7 @@ CONDITION_CLASSES: dict[str, list[str]] = {
|
||||
"Éclaircies",
|
||||
"Eclaircies",
|
||||
"Peu nuageux",
|
||||
"Variable",
|
||||
],
|
||||
ATTR_CONDITION_POURING: ["Pluie forte"],
|
||||
ATTR_CONDITION_RAINY: [
|
||||
@ -74,6 +76,7 @@ CONDITION_CLASSES: dict[str, list[str]] = {
|
||||
"Pluie modérée",
|
||||
"Pluie / Averses",
|
||||
"Averses",
|
||||
"Averses faibles",
|
||||
"Pluie",
|
||||
],
|
||||
ATTR_CONDITION_SNOWY: [
|
||||
@ -81,6 +84,8 @@ CONDITION_CLASSES: dict[str, list[str]] = {
|
||||
"Neige",
|
||||
"Averses de neige",
|
||||
"Neige forte",
|
||||
"Neige faible",
|
||||
"Averses de neige faible",
|
||||
"Quelques flocons",
|
||||
],
|
||||
ATTR_CONDITION_SNOWY_RAINY: ["Pluie et neige", "Pluie verglaçante"],
|
||||
|
@ -84,8 +84,10 @@
|
||||
"options": {
|
||||
"apparent_power": "[%key:component::sensor::entity_component::apparent_power::name%]",
|
||||
"aqi": "[%key:component::sensor::entity_component::aqi::name%]",
|
||||
"area": "[%key:component::sensor::entity_component::area::name%]",
|
||||
"atmospheric_pressure": "[%key:component::sensor::entity_component::atmospheric_pressure::name%]",
|
||||
"battery": "[%key:component::sensor::entity_component::battery::name%]",
|
||||
"blood_glucose_concentration": "[%key:component::sensor::entity_component::blood_glucose_concentration::name%]",
|
||||
"carbon_dioxide": "[%key:component::sensor::entity_component::carbon_dioxide::name%]",
|
||||
"carbon_monoxide": "[%key:component::sensor::entity_component::carbon_monoxide::name%]",
|
||||
"conductivity": "[%key:component::sensor::entity_component::conductivity::name%]",
|
||||
|
@ -30,5 +30,5 @@
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["pysmartthings"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["pysmartthings==3.0.4"]
|
||||
"requirements": ["pysmartthings==3.0.5"]
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import VodafoneConfigEntry, VodafoneStationRouter
|
||||
|
||||
PLATFORMS = [Platform.BUTTON, Platform.DEVICE_TRACKER, Platform.SENSOR]
|
||||
@ -36,7 +35,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: VodafoneConfigEntry) ->
|
||||
coordinator = entry.runtime_data
|
||||
await coordinator.api.logout()
|
||||
await coordinator.api.close()
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2025
|
||||
MINOR_VERSION: Final = 4
|
||||
PATCH_VERSION: Final = "3"
|
||||
PATCH_VERSION: Final = "4"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 0)
|
||||
|
@ -1,10 +1,10 @@
|
||||
[build-system]
|
||||
requires = ["setuptools==77.0.3"]
|
||||
requires = ["setuptools==78.1.1"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2025.4.3"
|
||||
version = "2025.4.4"
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
|
6
requirements_all.txt
generated
6
requirements_all.txt
generated
@ -267,7 +267,7 @@ aiohasupervisor==0.3.0
|
||||
aiohomeconnect==0.16.3
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==3.2.13
|
||||
aiohomekit==3.2.14
|
||||
|
||||
# homeassistant.components.mcp_server
|
||||
aiohttp_sse==2.2.0
|
||||
@ -784,7 +784,7 @@ devolo-home-control-api==0.18.3
|
||||
devolo-plc-api==1.5.1
|
||||
|
||||
# homeassistant.components.chacon_dio
|
||||
dio-chacon-wifi-api==1.2.1
|
||||
dio-chacon-wifi-api==1.2.2
|
||||
|
||||
# homeassistant.components.directv
|
||||
directv==0.4.0
|
||||
@ -2319,7 +2319,7 @@ pysma==0.7.5
|
||||
pysmappee==0.2.29
|
||||
|
||||
# homeassistant.components.smartthings
|
||||
pysmartthings==3.0.4
|
||||
pysmartthings==3.0.5
|
||||
|
||||
# homeassistant.components.smarty
|
||||
pysmarty2==0.10.2
|
||||
|
6
requirements_test_all.txt
generated
6
requirements_test_all.txt
generated
@ -252,7 +252,7 @@ aiohasupervisor==0.3.0
|
||||
aiohomeconnect==0.16.3
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==3.2.13
|
||||
aiohomekit==3.2.14
|
||||
|
||||
# homeassistant.components.mcp_server
|
||||
aiohttp_sse==2.2.0
|
||||
@ -675,7 +675,7 @@ devolo-home-control-api==0.18.3
|
||||
devolo-plc-api==1.5.1
|
||||
|
||||
# homeassistant.components.chacon_dio
|
||||
dio-chacon-wifi-api==1.2.1
|
||||
dio-chacon-wifi-api==1.2.2
|
||||
|
||||
# homeassistant.components.directv
|
||||
directv==0.4.0
|
||||
@ -1889,7 +1889,7 @@ pysma==0.7.5
|
||||
pysmappee==0.2.29
|
||||
|
||||
# homeassistant.components.smartthings
|
||||
pysmartthings==3.0.4
|
||||
pysmartthings==3.0.5
|
||||
|
||||
# homeassistant.components.smarty
|
||||
pysmarty2==0.10.2
|
||||
|
@ -191,7 +191,6 @@ EXCEPTIONS = {
|
||||
"enocean", # https://github.com/kipe/enocean/pull/142
|
||||
"imutils", # https://github.com/PyImageSearch/imutils/pull/292
|
||||
"iso4217", # Public domain
|
||||
"jaraco.itertools", # MIT - https://github.com/jaraco/jaraco.itertools/issues/21
|
||||
"kiwiki_client", # https://github.com/c7h/kiwiki_client/pull/6
|
||||
"ld2410-ble", # https://github.com/930913/ld2410-ble/pull/7
|
||||
"maxcube-api", # https://github.com/uebelack/python-maxcube-api/pull/48
|
||||
@ -205,6 +204,11 @@ EXCEPTIONS = {
|
||||
"repoze.lru",
|
||||
"sharp_aquos_rc", # https://github.com/jmoore987/sharp_aquos_rc/pull/14
|
||||
"tapsaff", # https://github.com/bazwilliams/python-taps-aff/pull/5
|
||||
# ---
|
||||
# https://github.com/jaraco/skeleton/pull/170
|
||||
# https://github.com/jaraco/skeleton/pull/171
|
||||
"jaraco.itertools", # MIT - https://github.com/jaraco/jaraco.itertools/issues/21
|
||||
"setuptools", # MIT
|
||||
}
|
||||
|
||||
TODO = {
|
||||
|
@ -181,5 +181,29 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Hood": {
|
||||
"data": {
|
||||
"programs": [
|
||||
{
|
||||
"key": "Cooking.Common.Program.Hood.Automatic",
|
||||
"constraints": {
|
||||
"execution": "selectandstart"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Cooking.Common.Program.Hood.Venting",
|
||||
"constraints": {
|
||||
"execution": "selectandstart"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "Cooking.Common.Program.Hood.DelayedShutOff",
|
||||
"constraints": {
|
||||
"execution": "selectandstart"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,9 @@
|
||||
'ha_id': 'BOSCH-HCS000000-D00000000004',
|
||||
'name': 'Hood',
|
||||
'programs': list([
|
||||
'Cooking.Common.Program.Hood.Automatic',
|
||||
'Cooking.Common.Program.Hood.Venting',
|
||||
'Cooking.Common.Program.Hood.DelayedShutOff',
|
||||
]),
|
||||
'settings': dict({
|
||||
'BSH.Common.Setting.AmbientLightBrightness': 70,
|
||||
|
@ -11,6 +11,7 @@ from aiohomeconnect.model import (
|
||||
EventMessage,
|
||||
EventType,
|
||||
HomeAppliance,
|
||||
StatusKey,
|
||||
)
|
||||
from aiohomeconnect.model.error import HomeConnectApiError
|
||||
import pytest
|
||||
@ -115,9 +116,19 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Washer",
|
||||
(StatusKey.BSH_COMMON_REMOTE_CONTROL_ACTIVE,),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -148,7 +159,17 @@ async def test_connected_devices(
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.BINARY_SENSOR,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{EventKey.BSH_COMMON_APPLIANCE_CONNECTED}",
|
||||
)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.BINARY_SENSOR,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -161,10 +182,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in (*keys_to_check, EventKey.BSH_COMMON_APPLIANCE_CONNECTED):
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.BINARY_SENSOR,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
|
@ -99,9 +99,19 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Washer",
|
||||
(CommandKey.BSH_COMMON_PAUSE_PROGRAM,),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -116,7 +126,7 @@ async def test_connected_devices(
|
||||
not be obtained while disconnected and once connected, the entities are added.
|
||||
"""
|
||||
get_available_commands_original_mock = client.get_available_commands
|
||||
get_available_programs_mock = client.get_available_programs
|
||||
get_all_programs_mock = client.get_all_programs
|
||||
|
||||
async def get_available_commands_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
@ -125,28 +135,36 @@ async def test_connected_devices(
|
||||
)
|
||||
return await get_available_commands_original_mock.side_effect(ha_id)
|
||||
|
||||
async def get_available_programs_side_effect(ha_id: str):
|
||||
async def get_all_programs_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
raise HomeConnectApiError(
|
||||
"SDK.Error.HomeAppliance.Connection.Initialization.Failed"
|
||||
)
|
||||
return await get_available_programs_mock.side_effect(ha_id)
|
||||
return await get_all_programs_mock.side_effect(ha_id)
|
||||
|
||||
client.get_available_commands = AsyncMock(
|
||||
side_effect=get_available_commands_side_effect
|
||||
)
|
||||
client.get_available_programs = AsyncMock(
|
||||
side_effect=get_available_programs_side_effect
|
||||
)
|
||||
client.get_all_programs = AsyncMock(side_effect=get_all_programs_side_effect)
|
||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||
assert await integration_setup(client)
|
||||
assert config_entry.state == ConfigEntryState.LOADED
|
||||
client.get_available_commands = get_available_commands_original_mock
|
||||
client.get_available_programs = get_available_programs_mock
|
||||
client.get_all_programs = get_all_programs_mock
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.BUTTON,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-StopProgram",
|
||||
)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.BUTTON,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -159,10 +177,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in (*keys_to_check, "StopProgram"):
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.BUTTON,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
|
@ -119,9 +119,19 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Hood",
|
||||
(SettingKey.COOKING_COMMON_LIGHTING,),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -136,7 +146,6 @@ async def test_connected_devices(
|
||||
not be obtained while disconnected and once connected, the entities are added.
|
||||
"""
|
||||
get_settings_original_mock = client.get_settings
|
||||
get_available_programs_mock = client.get_available_programs
|
||||
|
||||
async def get_settings_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
@ -145,26 +154,20 @@ async def test_connected_devices(
|
||||
)
|
||||
return await get_settings_original_mock.side_effect(ha_id)
|
||||
|
||||
async def get_available_programs_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
raise HomeConnectApiError(
|
||||
"SDK.Error.HomeAppliance.Connection.Initialization.Failed"
|
||||
)
|
||||
return await get_available_programs_mock.side_effect(ha_id)
|
||||
|
||||
client.get_settings = AsyncMock(side_effect=get_settings_side_effect)
|
||||
client.get_available_programs = AsyncMock(
|
||||
side_effect=get_available_programs_side_effect
|
||||
)
|
||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||
assert await integration_setup(client)
|
||||
assert config_entry.state == ConfigEntryState.LOADED
|
||||
client.get_settings = get_settings_original_mock
|
||||
client.get_available_programs = get_available_programs_mock
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.LIGHT,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -177,10 +180,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.LIGHT,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Hood"], indirect=True)
|
||||
|
@ -135,9 +135,21 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"FridgeFreezer",
|
||||
(
|
||||
SettingKey.REFRIGERATION_FRIDGE_FREEZER_SETPOINT_TEMPERATURE_REFRIGERATOR,
|
||||
),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -168,7 +180,12 @@ async def test_connected_devices(
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.NUMBER,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -181,10 +198,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.NUMBER,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["FridgeFreezer"], indirect=True)
|
||||
|
@ -20,6 +20,7 @@ from aiohomeconnect.model import (
|
||||
)
|
||||
from aiohomeconnect.model.error import (
|
||||
ActiveProgramNotSetError,
|
||||
HomeConnectApiError,
|
||||
HomeConnectError,
|
||||
SelectedProgramNotSetError,
|
||||
TooManyRequestsError,
|
||||
@ -138,9 +139,23 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Hood",
|
||||
(
|
||||
EventKey.BSH_COMMON_ROOT_ACTIVE_PROGRAM,
|
||||
EventKey.BSH_COMMON_ROOT_SELECTED_PROGRAM,
|
||||
SettingKey.COOKING_HOOD_COLOR_TEMPERATURE,
|
||||
),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -154,13 +169,39 @@ async def test_connected_devices(
|
||||
Specifically those devices whose settings, status, etc. could
|
||||
not be obtained while disconnected and once connected, the entities are added.
|
||||
"""
|
||||
get_settings_original_mock = client.get_settings
|
||||
get_all_programs_mock = client.get_all_programs
|
||||
|
||||
async def get_settings_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
raise HomeConnectApiError(
|
||||
"SDK.Error.HomeAppliance.Connection.Initialization.Failed"
|
||||
)
|
||||
return await get_settings_original_mock.side_effect(ha_id)
|
||||
|
||||
async def get_all_programs_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
raise HomeConnectApiError(
|
||||
"SDK.Error.HomeAppliance.Connection.Initialization.Failed"
|
||||
)
|
||||
return await get_all_programs_mock.side_effect(ha_id)
|
||||
|
||||
client.get_settings = AsyncMock(side_effect=get_settings_side_effect)
|
||||
client.get_all_programs = AsyncMock(side_effect=get_all_programs_side_effect)
|
||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||
assert await integration_setup(client)
|
||||
assert config_entry.state == ConfigEntryState.LOADED
|
||||
client.get_settings = get_settings_original_mock
|
||||
client.get_all_programs = get_all_programs_mock
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.SELECT,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -173,10 +214,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert entity_entries
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.SELECT,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
|
@ -154,9 +154,19 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Washer",
|
||||
(StatusKey.BSH_COMMON_OPERATION_STATE,),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -187,7 +197,12 @@ async def test_connected_devices(
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.SENSOR,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -200,10 +215,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.SENSOR,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", [TEST_HC_APP], indirect=True)
|
||||
|
@ -147,9 +147,23 @@ async def test_paired_depaired_devices_flow(
|
||||
assert entity_registry.async_get(entity_entry.entity_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("appliance", ["Washer"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Washer",
|
||||
(
|
||||
SettingKey.BSH_COMMON_POWER_STATE,
|
||||
SettingKey.BSH_COMMON_CHILD_LOCK,
|
||||
"Program Cotton",
|
||||
),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -164,7 +178,7 @@ async def test_connected_devices(
|
||||
not be obtained while disconnected and once connected, the entities are added.
|
||||
"""
|
||||
get_settings_original_mock = client.get_settings
|
||||
get_available_programs_mock = client.get_available_programs
|
||||
get_all_programs_mock = client.get_all_programs
|
||||
|
||||
async def get_settings_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
@ -173,26 +187,29 @@ async def test_connected_devices(
|
||||
)
|
||||
return await get_settings_original_mock.side_effect(ha_id)
|
||||
|
||||
async def get_available_programs_side_effect(ha_id: str):
|
||||
async def get_all_programs_side_effect(ha_id: str):
|
||||
if ha_id == appliance.ha_id:
|
||||
raise HomeConnectApiError(
|
||||
"SDK.Error.HomeAppliance.Connection.Initialization.Failed"
|
||||
)
|
||||
return await get_available_programs_mock.side_effect(ha_id)
|
||||
return await get_all_programs_mock.side_effect(ha_id)
|
||||
|
||||
client.get_settings = AsyncMock(side_effect=get_settings_side_effect)
|
||||
client.get_available_programs = AsyncMock(
|
||||
side_effect=get_available_programs_side_effect
|
||||
)
|
||||
client.get_all_programs = AsyncMock(side_effect=get_all_programs_side_effect)
|
||||
assert config_entry.state == ConfigEntryState.NOT_LOADED
|
||||
assert await integration_setup(client)
|
||||
assert config_entry.state == ConfigEntryState.LOADED
|
||||
client.get_settings = get_settings_original_mock
|
||||
client.get_available_programs = get_available_programs_mock
|
||||
client.get_all_programs = get_all_programs_mock
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.SWITCH,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -205,10 +222,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.SWITCH,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
|
@ -113,9 +113,19 @@ async def test_paired_depaired_devices_flow(
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
@pytest.mark.parametrize("appliance", ["Oven"], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
("appliance", "keys_to_check"),
|
||||
[
|
||||
(
|
||||
"Oven",
|
||||
(SettingKey.BSH_COMMON_ALARM_CLOCK,),
|
||||
)
|
||||
],
|
||||
indirect=["appliance"],
|
||||
)
|
||||
async def test_connected_devices(
|
||||
appliance: HomeAppliance,
|
||||
keys_to_check: tuple,
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry,
|
||||
integration_setup: Callable[[MagicMock], Awaitable[bool]],
|
||||
@ -146,7 +156,12 @@ async def test_connected_devices(
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
for key in keys_to_check:
|
||||
assert not entity_registry.async_get_entity_id(
|
||||
Platform.TIME,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
await client.add_events(
|
||||
[
|
||||
@ -159,10 +174,12 @@ async def test_connected_devices(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, appliance.ha_id)})
|
||||
assert device
|
||||
new_entity_entries = entity_registry.entities.get_entries_for_device_id(device.id)
|
||||
assert len(new_entity_entries) > len(entity_entries)
|
||||
for key in keys_to_check:
|
||||
assert entity_registry.async_get_entity_id(
|
||||
Platform.TIME,
|
||||
DOMAIN,
|
||||
f"{appliance.ha_id}-{key}",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
|
@ -5,7 +5,7 @@ from datetime import UTC, datetime
|
||||
from aiovodafone import VodafoneStationDevice
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.vodafone_station import DOMAIN
|
||||
from homeassistant.components.vodafone_station.const import DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||
|
||||
from .const import DEVICE_1_HOST, DEVICE_1_MAC, DEVICE_2_MAC
|
||||
|
@ -3,6 +3,8 @@
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from homeassistant.components.device_tracker import CONF_CONSIDER_HOME
|
||||
from homeassistant.components.vodafone_station.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
@ -31,3 +33,21 @@ async def test_reload_config_entry_with_options(
|
||||
assert result["data"] == {
|
||||
CONF_CONSIDER_HOME: 37,
|
||||
}
|
||||
|
||||
|
||||
async def test_unload_entry(
|
||||
hass: HomeAssistant,
|
||||
mock_vodafone_station_router: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test unloading the config entry."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
assert await hass.config_entries.async_unload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert mock_config_entry.state is ConfigEntryState.NOT_LOADED
|
||||
assert not hass.data.get(DOMAIN)
|
||||
|
Loading…
x
Reference in New Issue
Block a user