mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Use BSH keys as unique ID's suffix at Home Connect (#126143)
* Use BSH keys as as unique id suffix instead of the simple description * Update tests/components/home_connect/test_init.py --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
3e8bc98f23
commit
0d795aad16
@ -4,18 +4,20 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import ATTR_DEVICE_ID, CONF_DEVICE, Platform
|
from homeassistant.const import ATTR_DEVICE_ID, CONF_DEVICE, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
config_entry_oauth2_flow,
|
config_entry_oauth2_flow,
|
||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
device_registry as dr,
|
device_registry as dr,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.entity_registry import RegistryEntry, async_migrate_entries
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ from .const import (
|
|||||||
BSH_PAUSE,
|
BSH_PAUSE,
|
||||||
BSH_RESUME,
|
BSH_RESUME,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
OLD_NEW_UNIQUE_ID_SUFFIX_MAP,
|
||||||
SERVICE_OPTION_ACTIVE,
|
SERVICE_OPTION_ACTIVE,
|
||||||
SERVICE_OPTION_SELECTED,
|
SERVICE_OPTION_SELECTED,
|
||||||
SERVICE_PAUSE_PROGRAM,
|
SERVICE_PAUSE_PROGRAM,
|
||||||
@ -268,3 +271,31 @@ async def update_all_devices(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
|||||||
await hass.async_add_executor_job(device.initialize)
|
await hass.async_add_executor_job(device.initialize)
|
||||||
except HTTPError as err:
|
except HTTPError as err:
|
||||||
_LOGGER.warning("Cannot update devices: %s", err.response.status_code)
|
_LOGGER.warning("Cannot update devices: %s", err.response.status_code)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||||
|
"""Migrate old entry."""
|
||||||
|
_LOGGER.debug("Migrating from version %s", config_entry.version)
|
||||||
|
|
||||||
|
if config_entry.version == 1 and config_entry.minor_version == 1:
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def update_unique_id(
|
||||||
|
entity_entry: RegistryEntry,
|
||||||
|
) -> dict[str, Any] | None:
|
||||||
|
"""Update unique ID of entity entry."""
|
||||||
|
for old_id_suffix, new_id_suffix in OLD_NEW_UNIQUE_ID_SUFFIX_MAP.items():
|
||||||
|
if entity_entry.unique_id.endswith(f"-{old_id_suffix}"):
|
||||||
|
return {
|
||||||
|
"new_unique_id": entity_entry.unique_id.replace(
|
||||||
|
old_id_suffix, new_id_suffix
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return None
|
||||||
|
|
||||||
|
await async_migrate_entries(hass, config_entry.entry_id, update_unique_id)
|
||||||
|
|
||||||
|
hass.config_entries.async_update_entry(config_entry, minor_version=2)
|
||||||
|
|
||||||
|
_LOGGER.debug("Migration to version %s successful", config_entry.version)
|
||||||
|
return True
|
||||||
|
@ -24,6 +24,7 @@ from homeassistant.helpers.dispatcher import dispatcher_send
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_AMBIENT,
|
ATTR_AMBIENT,
|
||||||
|
ATTR_BSH_KEY,
|
||||||
ATTR_DESC,
|
ATTR_DESC,
|
||||||
ATTR_DEVICE,
|
ATTR_DEVICE,
|
||||||
ATTR_KEY,
|
ATTR_KEY,
|
||||||
@ -32,9 +33,16 @@ from .const import (
|
|||||||
ATTR_UNIT,
|
ATTR_UNIT,
|
||||||
ATTR_VALUE,
|
ATTR_VALUE,
|
||||||
BSH_ACTIVE_PROGRAM,
|
BSH_ACTIVE_PROGRAM,
|
||||||
|
BSH_AMBIENT_LIGHT_ENABLED,
|
||||||
|
BSH_COMMON_OPTION_DURATION,
|
||||||
|
BSH_COMMON_OPTION_PROGRAM_PROGRESS,
|
||||||
BSH_OPERATION_STATE,
|
BSH_OPERATION_STATE,
|
||||||
BSH_POWER_OFF,
|
BSH_POWER_OFF,
|
||||||
BSH_POWER_STANDBY,
|
BSH_POWER_STANDBY,
|
||||||
|
BSH_REMAINING_PROGRAM_TIME,
|
||||||
|
BSH_REMOTE_CONTROL_ACTIVATION_STATE,
|
||||||
|
BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
|
COOKING_LIGHTING,
|
||||||
SIGNAL_UPDATE_ENTITIES,
|
SIGNAL_UPDATE_ENTITIES,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -181,21 +189,39 @@ class DeviceWithPrograms(HomeConnectDevice):
|
|||||||
device.
|
device.
|
||||||
"""
|
"""
|
||||||
sensors = {
|
sensors = {
|
||||||
"Remaining Program Time": (None, None, SensorDeviceClass.TIMESTAMP, 1),
|
BSH_REMAINING_PROGRAM_TIME: (
|
||||||
"Duration": (UnitOfTime.SECONDS, "mdi:update", None, 1),
|
"Remaining Program Time",
|
||||||
"Program Progress": (PERCENTAGE, "mdi:progress-clock", None, 1),
|
None,
|
||||||
|
None,
|
||||||
|
SensorDeviceClass.TIMESTAMP,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
BSH_COMMON_OPTION_DURATION: (
|
||||||
|
"Duration",
|
||||||
|
UnitOfTime.SECONDS,
|
||||||
|
"mdi:update",
|
||||||
|
None,
|
||||||
|
1,
|
||||||
|
),
|
||||||
|
BSH_COMMON_OPTION_PROGRAM_PROGRESS: (
|
||||||
|
"Program Progress",
|
||||||
|
PERCENTAGE,
|
||||||
|
"mdi:progress-clock",
|
||||||
|
None,
|
||||||
|
1,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
ATTR_DEVICE: self,
|
ATTR_DEVICE: self,
|
||||||
ATTR_DESC: k,
|
ATTR_BSH_KEY: k,
|
||||||
|
ATTR_DESC: desc,
|
||||||
ATTR_UNIT: unit,
|
ATTR_UNIT: unit,
|
||||||
ATTR_KEY: f"BSH.Common.Option.{k.replace(' ', '')}",
|
|
||||||
ATTR_ICON: icon,
|
ATTR_ICON: icon,
|
||||||
ATTR_DEVICE_CLASS: device_class,
|
ATTR_DEVICE_CLASS: device_class,
|
||||||
ATTR_SIGN: sign,
|
ATTR_SIGN: sign,
|
||||||
}
|
}
|
||||||
for k, (unit, icon, device_class, sign) in sensors.items()
|
for k, (desc, unit, icon, device_class, sign) in sensors.items()
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -208,9 +234,9 @@ class DeviceWithOpState(HomeConnectDevice):
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
ATTR_DEVICE: self,
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: BSH_OPERATION_STATE,
|
||||||
ATTR_DESC: "Operation State",
|
ATTR_DESC: "Operation State",
|
||||||
ATTR_UNIT: None,
|
ATTR_UNIT: None,
|
||||||
ATTR_KEY: BSH_OPERATION_STATE,
|
|
||||||
ATTR_ICON: "mdi:state-machine",
|
ATTR_ICON: "mdi:state-machine",
|
||||||
ATTR_DEVICE_CLASS: None,
|
ATTR_DEVICE_CLASS: None,
|
||||||
ATTR_SIGN: 1,
|
ATTR_SIGN: 1,
|
||||||
@ -225,6 +251,7 @@ class DeviceWithDoor(HomeConnectDevice):
|
|||||||
"""Get a dictionary with info about the door binary sensor."""
|
"""Get a dictionary with info about the door binary sensor."""
|
||||||
return {
|
return {
|
||||||
ATTR_DEVICE: self,
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: "Door",
|
||||||
ATTR_DESC: "Door",
|
ATTR_DESC: "Door",
|
||||||
ATTR_SENSOR_TYPE: "door",
|
ATTR_SENSOR_TYPE: "door",
|
||||||
ATTR_DEVICE_CLASS: "door",
|
ATTR_DEVICE_CLASS: "door",
|
||||||
@ -236,7 +263,12 @@ class DeviceWithLight(HomeConnectDevice):
|
|||||||
|
|
||||||
def get_light_entity(self) -> dict[str, Any]:
|
def get_light_entity(self) -> dict[str, Any]:
|
||||||
"""Get a dictionary with info about the lighting."""
|
"""Get a dictionary with info about the lighting."""
|
||||||
return {ATTR_DEVICE: self, ATTR_DESC: "Light", ATTR_AMBIENT: None}
|
return {
|
||||||
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: COOKING_LIGHTING,
|
||||||
|
ATTR_DESC: "Light",
|
||||||
|
ATTR_AMBIENT: None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DeviceWithAmbientLight(HomeConnectDevice):
|
class DeviceWithAmbientLight(HomeConnectDevice):
|
||||||
@ -244,7 +276,12 @@ class DeviceWithAmbientLight(HomeConnectDevice):
|
|||||||
|
|
||||||
def get_ambientlight_entity(self) -> dict[str, Any]:
|
def get_ambientlight_entity(self) -> dict[str, Any]:
|
||||||
"""Get a dictionary with info about the ambient lighting."""
|
"""Get a dictionary with info about the ambient lighting."""
|
||||||
return {ATTR_DEVICE: self, ATTR_DESC: "AmbientLight", ATTR_AMBIENT: True}
|
return {
|
||||||
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: BSH_AMBIENT_LIGHT_ENABLED,
|
||||||
|
ATTR_DESC: "AmbientLight",
|
||||||
|
ATTR_AMBIENT: True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DeviceWithRemoteControl(HomeConnectDevice):
|
class DeviceWithRemoteControl(HomeConnectDevice):
|
||||||
@ -254,6 +291,7 @@ class DeviceWithRemoteControl(HomeConnectDevice):
|
|||||||
"""Get a dictionary with info about the remote control sensor."""
|
"""Get a dictionary with info about the remote control sensor."""
|
||||||
return {
|
return {
|
||||||
ATTR_DEVICE: self,
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: BSH_REMOTE_CONTROL_ACTIVATION_STATE,
|
||||||
ATTR_DESC: "Remote Control",
|
ATTR_DESC: "Remote Control",
|
||||||
ATTR_SENSOR_TYPE: "remote_control",
|
ATTR_SENSOR_TYPE: "remote_control",
|
||||||
}
|
}
|
||||||
@ -266,6 +304,7 @@ class DeviceWithRemoteStart(HomeConnectDevice):
|
|||||||
"""Get a dictionary with info about the remote start sensor."""
|
"""Get a dictionary with info about the remote start sensor."""
|
||||||
return {
|
return {
|
||||||
ATTR_DEVICE: self,
|
ATTR_DEVICE: self,
|
||||||
|
ATTR_BSH_KEY: BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
ATTR_DESC: "Remote Start",
|
ATTR_DESC: "Remote Start",
|
||||||
ATTR_SENSOR_TYPE: "remote_start",
|
ATTR_SENSOR_TYPE: "remote_start",
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class HomeConnectBinarySensorEntityDescription(BinarySensorEntityDescription):
|
class HomeConnectBinarySensorEntityDescription(BinarySensorEntityDescription):
|
||||||
"""Entity Description class for binary sensors."""
|
"""Entity Description class for binary sensors."""
|
||||||
|
|
||||||
state_key: str | None
|
desc: str
|
||||||
device_class: BinarySensorDeviceClass | None = BinarySensorDeviceClass.DOOR
|
device_class: BinarySensorDeviceClass | None = BinarySensorDeviceClass.DOOR
|
||||||
boolean_map: dict[str, bool] = field(
|
boolean_map: dict[str, bool] = field(
|
||||||
default_factory=lambda: {
|
default_factory=lambda: {
|
||||||
@ -51,16 +51,16 @@ class HomeConnectBinarySensorEntityDescription(BinarySensorEntityDescription):
|
|||||||
|
|
||||||
BINARY_SENSORS: tuple[HomeConnectBinarySensorEntityDescription, ...] = (
|
BINARY_SENSORS: tuple[HomeConnectBinarySensorEntityDescription, ...] = (
|
||||||
HomeConnectBinarySensorEntityDescription(
|
HomeConnectBinarySensorEntityDescription(
|
||||||
key="Chiller Door",
|
key=REFRIGERATION_STATUS_DOOR_CHILLER,
|
||||||
state_key=REFRIGERATION_STATUS_DOOR_CHILLER,
|
desc="Chiller Door",
|
||||||
),
|
),
|
||||||
HomeConnectBinarySensorEntityDescription(
|
HomeConnectBinarySensorEntityDescription(
|
||||||
key="Freezer Door",
|
key=REFRIGERATION_STATUS_DOOR_FREEZER,
|
||||||
state_key=REFRIGERATION_STATUS_DOOR_FREEZER,
|
desc="Freezer Door",
|
||||||
),
|
),
|
||||||
HomeConnectBinarySensorEntityDescription(
|
HomeConnectBinarySensorEntityDescription(
|
||||||
key="Refrigerator Door",
|
key=REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
state_key=REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
desc="Refrigerator Door",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ async def async_setup_entry(
|
|||||||
device=device, entity_description=description
|
device=device, entity_description=description
|
||||||
)
|
)
|
||||||
for description in BINARY_SENSORS
|
for description in BINARY_SENSORS
|
||||||
if description.state_key in device.appliance.status
|
if description.key in device.appliance.status
|
||||||
)
|
)
|
||||||
return entities
|
return entities
|
||||||
|
|
||||||
@ -98,12 +98,13 @@ class HomeConnectBinarySensor(HomeConnectEntity, BinarySensorEntity):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
device: HomeConnectDevice,
|
device: HomeConnectDevice,
|
||||||
|
bsh_key: str,
|
||||||
desc: str,
|
desc: str,
|
||||||
sensor_type: str,
|
sensor_type: str,
|
||||||
device_class: BinarySensorDeviceClass | None = None,
|
device_class: BinarySensorDeviceClass | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, desc)
|
super().__init__(device, bsh_key, desc)
|
||||||
self._attr_device_class = device_class
|
self._attr_device_class = device_class
|
||||||
self._type = sensor_type
|
self._type = sensor_type
|
||||||
self._false_value_list = None
|
self._false_value_list = None
|
||||||
@ -162,7 +163,7 @@ class HomeConnectFridgeDoorBinarySensor(HomeConnectEntity, BinarySensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
super().__init__(device, entity_description.key)
|
super().__init__(device, entity_description.key, entity_description.desc)
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update the binary sensor's status."""
|
"""Update the binary sensor's status."""
|
||||||
@ -172,9 +173,7 @@ class HomeConnectFridgeDoorBinarySensor(HomeConnectEntity, BinarySensorEntity):
|
|||||||
self.state,
|
self.state,
|
||||||
)
|
)
|
||||||
self._attr_is_on = self.entity_description.boolean_map.get(
|
self._attr_is_on = self.entity_description.boolean_map.get(
|
||||||
self.device.appliance.status.get(self.entity_description.state_key, {}).get(
|
self.device.appliance.status.get(self.bsh_key, {}).get(ATTR_VALUE)
|
||||||
ATTR_VALUE
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
self._attr_available = self._attr_is_on is not None
|
self._attr_available = self._attr_is_on is not None
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
|
@ -14,6 +14,8 @@ class OAuth2FlowHandler(
|
|||||||
|
|
||||||
DOMAIN = DOMAIN
|
DOMAIN = DOMAIN
|
||||||
|
|
||||||
|
MINOR_VERSION = 2
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def logger(self) -> logging.Logger:
|
def logger(self) -> logging.Logger:
|
||||||
"""Return logger."""
|
"""Return logger."""
|
||||||
|
@ -14,6 +14,10 @@ BSH_REMOTE_CONTROL_ACTIVATION_STATE = "BSH.Common.Status.RemoteControlActive"
|
|||||||
BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed"
|
BSH_REMOTE_START_ALLOWANCE_STATE = "BSH.Common.Status.RemoteControlStartAllowed"
|
||||||
BSH_CHILD_LOCK_STATE = "BSH.Common.Setting.ChildLock"
|
BSH_CHILD_LOCK_STATE = "BSH.Common.Setting.ChildLock"
|
||||||
|
|
||||||
|
BSH_REMAINING_PROGRAM_TIME = "BSH.Common.Option.RemainingProgramTime"
|
||||||
|
BSH_COMMON_OPTION_DURATION = "BSH.Common.Option.Duration"
|
||||||
|
BSH_COMMON_OPTION_PROGRAM_PROGRESS = "BSH.Common.Option.ProgramProgress"
|
||||||
|
|
||||||
BSH_EVENT_PRESENT_STATE_PRESENT = "BSH.Common.EnumType.EventPresentState.Present"
|
BSH_EVENT_PRESENT_STATE_PRESENT = "BSH.Common.EnumType.EventPresentState.Present"
|
||||||
BSH_EVENT_PRESENT_STATE_CONFIRMED = "BSH.Common.EnumType.EventPresentState.Confirmed"
|
BSH_EVENT_PRESENT_STATE_CONFIRMED = "BSH.Common.EnumType.EventPresentState.Confirmed"
|
||||||
BSH_EVENT_PRESENT_STATE_OFF = "BSH.Common.EnumType.EventPresentState.Off"
|
BSH_EVENT_PRESENT_STATE_OFF = "BSH.Common.EnumType.EventPresentState.Off"
|
||||||
@ -92,6 +96,7 @@ SERVICE_SETTING = "change_setting"
|
|||||||
SERVICE_START_PROGRAM = "start_program"
|
SERVICE_START_PROGRAM = "start_program"
|
||||||
|
|
||||||
ATTR_AMBIENT = "ambient"
|
ATTR_AMBIENT = "ambient"
|
||||||
|
ATTR_BSH_KEY = "bsh_key"
|
||||||
ATTR_DESC = "desc"
|
ATTR_DESC = "desc"
|
||||||
ATTR_DEVICE = "device"
|
ATTR_DEVICE = "device"
|
||||||
ATTR_KEY = "key"
|
ATTR_KEY = "key"
|
||||||
@ -100,3 +105,30 @@ ATTR_SENSOR_TYPE = "sensor_type"
|
|||||||
ATTR_SIGN = "sign"
|
ATTR_SIGN = "sign"
|
||||||
ATTR_UNIT = "unit"
|
ATTR_UNIT = "unit"
|
||||||
ATTR_VALUE = "value"
|
ATTR_VALUE = "value"
|
||||||
|
|
||||||
|
OLD_NEW_UNIQUE_ID_SUFFIX_MAP = {
|
||||||
|
"ChildLock": BSH_CHILD_LOCK_STATE,
|
||||||
|
"Operation State": BSH_OPERATION_STATE,
|
||||||
|
"Light": COOKING_LIGHTING,
|
||||||
|
"AmbientLight": BSH_AMBIENT_LIGHT_ENABLED,
|
||||||
|
"Power": BSH_POWER_STATE,
|
||||||
|
"Remaining Program Time": BSH_REMAINING_PROGRAM_TIME,
|
||||||
|
"Duration": BSH_COMMON_OPTION_DURATION,
|
||||||
|
"Program Progress": BSH_COMMON_OPTION_PROGRAM_PROGRESS,
|
||||||
|
"Remote Control": BSH_REMOTE_CONTROL_ACTIVATION_STATE,
|
||||||
|
"Remote Start": BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
|
"Supermode Freezer": REFRIGERATION_SUPERMODEFREEZER,
|
||||||
|
"Supermode Refrigerator": REFRIGERATION_SUPERMODEREFRIGERATOR,
|
||||||
|
"Dispenser Enabled": REFRIGERATION_DISPENSER,
|
||||||
|
"Internal Light": REFRIGERATION_INTERNAL_LIGHT_POWER,
|
||||||
|
"External Light": REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
||||||
|
"Chiller Door": REFRIGERATION_STATUS_DOOR_CHILLER,
|
||||||
|
"Freezer Door": REFRIGERATION_STATUS_DOOR_FREEZER,
|
||||||
|
"Refrigerator Door": REFRIGERATION_STATUS_DOOR_REFRIGERATOR,
|
||||||
|
"Door Alarm Freezer": REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
|
"Door Alarm Refrigerator": REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR,
|
||||||
|
"Temperature Alarm Freezer": REFRIGERATION_EVENT_TEMP_ALARM_FREEZER,
|
||||||
|
"Bean Container Empty": COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
|
"Water Tank Empty": COFFEE_EVENT_WATER_TANK_EMPTY,
|
||||||
|
"Drip Tray Full": COFFEE_EVENT_DRIP_TRAY_FULL,
|
||||||
|
}
|
||||||
|
@ -18,11 +18,12 @@ class HomeConnectEntity(Entity):
|
|||||||
|
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
|
|
||||||
def __init__(self, device: HomeConnectDevice, desc: str) -> None:
|
def __init__(self, device: HomeConnectDevice, bsh_key: str, desc: str) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
self.device = device
|
self.device = device
|
||||||
|
self.bsh_key = bsh_key
|
||||||
self._attr_name = f"{device.appliance.name} {desc}"
|
self._attr_name = f"{device.appliance.name} {desc}"
|
||||||
self._attr_unique_id = f"{device.appliance.haId}-{desc}"
|
self._attr_unique_id = f"{device.appliance.haId}-{bsh_key}"
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
identifiers={(DOMAIN, device.appliance.haId)},
|
identifiers={(DOMAIN, device.appliance.haId)},
|
||||||
manufacturer=device.appliance.brand,
|
manufacturer=device.appliance.brand,
|
||||||
|
@ -27,8 +27,6 @@ from .const import (
|
|||||||
BSH_AMBIENT_LIGHT_COLOR,
|
BSH_AMBIENT_LIGHT_COLOR,
|
||||||
BSH_AMBIENT_LIGHT_COLOR_CUSTOM_COLOR,
|
BSH_AMBIENT_LIGHT_COLOR_CUSTOM_COLOR,
|
||||||
BSH_AMBIENT_LIGHT_CUSTOM_COLOR,
|
BSH_AMBIENT_LIGHT_CUSTOM_COLOR,
|
||||||
BSH_AMBIENT_LIGHT_ENABLED,
|
|
||||||
COOKING_LIGHTING,
|
|
||||||
COOKING_LIGHTING_BRIGHTNESS,
|
COOKING_LIGHTING_BRIGHTNESS,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
||||||
@ -45,19 +43,19 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class HomeConnectLightEntityDescription(LightEntityDescription):
|
class HomeConnectLightEntityDescription(LightEntityDescription):
|
||||||
"""Light entity description."""
|
"""Light entity description."""
|
||||||
|
|
||||||
on_key: str
|
desc: str
|
||||||
brightness_key: str | None
|
brightness_key: str | None
|
||||||
|
|
||||||
|
|
||||||
LIGHTS: tuple[HomeConnectLightEntityDescription, ...] = (
|
LIGHTS: tuple[HomeConnectLightEntityDescription, ...] = (
|
||||||
HomeConnectLightEntityDescription(
|
HomeConnectLightEntityDescription(
|
||||||
key="Internal Light",
|
key=REFRIGERATION_INTERNAL_LIGHT_POWER,
|
||||||
on_key=REFRIGERATION_INTERNAL_LIGHT_POWER,
|
desc="Internal Light",
|
||||||
brightness_key=REFRIGERATION_INTERNAL_LIGHT_BRIGHTNESS,
|
brightness_key=REFRIGERATION_INTERNAL_LIGHT_BRIGHTNESS,
|
||||||
),
|
),
|
||||||
HomeConnectLightEntityDescription(
|
HomeConnectLightEntityDescription(
|
||||||
key="External Light",
|
key=REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
||||||
on_key=REFRIGERATION_EXTERNAL_LIGHT_POWER,
|
desc="External Light",
|
||||||
brightness_key=REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
brightness_key=REFRIGERATION_EXTERNAL_LIGHT_BRIGHTNESS,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -86,7 +84,7 @@ async def async_setup_entry(
|
|||||||
entity_description=description,
|
entity_description=description,
|
||||||
)
|
)
|
||||||
for description in LIGHTS
|
for description in LIGHTS
|
||||||
if description.on_key in device.appliance.status
|
if description.key in device.appliance.status
|
||||||
)
|
)
|
||||||
entities.extend(entity_list)
|
entities.extend(entity_list)
|
||||||
return entities
|
return entities
|
||||||
@ -97,9 +95,11 @@ async def async_setup_entry(
|
|||||||
class HomeConnectLight(HomeConnectEntity, LightEntity):
|
class HomeConnectLight(HomeConnectEntity, LightEntity):
|
||||||
"""Light for Home Connect."""
|
"""Light for Home Connect."""
|
||||||
|
|
||||||
def __init__(self, device, desc, ambient) -> None:
|
def __init__(
|
||||||
|
self, device: HomeConnectDevice, bsh_key: str, desc: str, ambient: bool
|
||||||
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, desc)
|
super().__init__(device, bsh_key, desc)
|
||||||
self._ambient = ambient
|
self._ambient = ambient
|
||||||
self._percentage_scale = (10, 100)
|
self._percentage_scale = (10, 100)
|
||||||
self._brightness_key: str | None
|
self._brightness_key: str | None
|
||||||
@ -107,14 +107,12 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
self._color_key: str | None
|
self._color_key: str | None
|
||||||
if ambient:
|
if ambient:
|
||||||
self._brightness_key = BSH_AMBIENT_LIGHT_BRIGHTNESS
|
self._brightness_key = BSH_AMBIENT_LIGHT_BRIGHTNESS
|
||||||
self._key = BSH_AMBIENT_LIGHT_ENABLED
|
|
||||||
self._custom_color_key = BSH_AMBIENT_LIGHT_CUSTOM_COLOR
|
self._custom_color_key = BSH_AMBIENT_LIGHT_CUSTOM_COLOR
|
||||||
self._color_key = BSH_AMBIENT_LIGHT_COLOR
|
self._color_key = BSH_AMBIENT_LIGHT_COLOR
|
||||||
self._attr_color_mode = ColorMode.HS
|
self._attr_color_mode = ColorMode.HS
|
||||||
self._attr_supported_color_modes = {ColorMode.HS}
|
self._attr_supported_color_modes = {ColorMode.HS}
|
||||||
else:
|
else:
|
||||||
self._brightness_key = COOKING_LIGHTING_BRIGHTNESS
|
self._brightness_key = COOKING_LIGHTING_BRIGHTNESS
|
||||||
self._key = COOKING_LIGHTING
|
|
||||||
self._custom_color_key = None
|
self._custom_color_key = None
|
||||||
self._color_key = None
|
self._color_key = None
|
||||||
self._attr_color_mode = ColorMode.BRIGHTNESS
|
self._attr_color_mode = ColorMode.BRIGHTNESS
|
||||||
@ -126,7 +124,7 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
_LOGGER.debug("Switching ambient light on for: %s", self.name)
|
_LOGGER.debug("Switching ambient light on for: %s", self.name)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self._key, True
|
self.device.appliance.set_setting, self.bsh_key, True
|
||||||
)
|
)
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying to turn on ambient light: %s", err)
|
_LOGGER.error("Error while trying to turn on ambient light: %s", err)
|
||||||
@ -189,7 +187,7 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
_LOGGER.debug("Switching light on for: %s", self.name)
|
_LOGGER.debug("Switching light on for: %s", self.name)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self._key, True
|
self.device.appliance.set_setting, self.bsh_key, True
|
||||||
)
|
)
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying to turn on light: %s", err)
|
_LOGGER.error("Error while trying to turn on light: %s", err)
|
||||||
@ -201,7 +199,7 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
_LOGGER.debug("Switching light off for: %s", self.name)
|
_LOGGER.debug("Switching light off for: %s", self.name)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self._key, False
|
self.device.appliance.set_setting, self.bsh_key, False
|
||||||
)
|
)
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying to turn off light: %s", err)
|
_LOGGER.error("Error while trying to turn off light: %s", err)
|
||||||
@ -209,9 +207,11 @@ class HomeConnectLight(HomeConnectEntity, LightEntity):
|
|||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update the light's status."""
|
"""Update the light's status."""
|
||||||
if self.device.appliance.status.get(self._key, {}).get(ATTR_VALUE) is True:
|
if self.device.appliance.status.get(self.bsh_key, {}).get(ATTR_VALUE) is True:
|
||||||
self._attr_is_on = True
|
self._attr_is_on = True
|
||||||
elif self.device.appliance.status.get(self._key, {}).get(ATTR_VALUE) is False:
|
elif (
|
||||||
|
self.device.appliance.status.get(self.bsh_key, {}).get(ATTR_VALUE) is False
|
||||||
|
):
|
||||||
self._attr_is_on = False
|
self._attr_is_on = False
|
||||||
else:
|
else:
|
||||||
self._attr_is_on = None
|
self._attr_is_on = None
|
||||||
@ -255,8 +255,9 @@ class HomeConnectCoolingLight(HomeConnectLight):
|
|||||||
entity_description: HomeConnectLightEntityDescription,
|
entity_description: HomeConnectLightEntityDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Cooling Light Entity."""
|
"""Initialize Cooling Light Entity."""
|
||||||
super().__init__(device, entity_description.key, ambient)
|
super().__init__(
|
||||||
|
device, entity_description.key, entity_description.desc, ambient
|
||||||
|
)
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
self._key = entity_description.on_key
|
|
||||||
self._brightness_key = entity_description.brightness_key
|
self._brightness_key = entity_description.brightness_key
|
||||||
self._percentage_scale = (1, 100)
|
self._percentage_scale = (1, 100)
|
||||||
|
@ -46,45 +46,39 @@ class HomeConnectSensorEntityDescription(SensorEntityDescription):
|
|||||||
options: list[str] | None = field(
|
options: list[str] | None = field(
|
||||||
default_factory=lambda: ["confirmed", "off", "present"]
|
default_factory=lambda: ["confirmed", "off", "present"]
|
||||||
)
|
)
|
||||||
state_key: str
|
desc: str
|
||||||
appliance_types: tuple[str, ...]
|
appliance_types: tuple[str, ...]
|
||||||
|
|
||||||
|
|
||||||
SENSORS: tuple[HomeConnectSensorEntityDescription, ...] = (
|
SENSORS: tuple[HomeConnectSensorEntityDescription, ...] = (
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Door Alarm Freezer",
|
key=REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
||||||
translation_key="alarm_sensor_freezer",
|
desc="Door Alarm Freezer",
|
||||||
state_key=REFRIGERATION_EVENT_DOOR_ALARM_FREEZER,
|
|
||||||
appliance_types=("FridgeFreezer", "Freezer"),
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Door Alarm Refrigerator",
|
key=REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR,
|
||||||
translation_key="alarm_sensor_fridge",
|
desc="Door Alarm Refrigerator",
|
||||||
state_key=REFRIGERATION_EVENT_DOOR_ALARM_REFRIGERATOR,
|
|
||||||
appliance_types=("FridgeFreezer", "Refrigerator"),
|
appliance_types=("FridgeFreezer", "Refrigerator"),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Temperature Alarm Freezer",
|
key=REFRIGERATION_EVENT_TEMP_ALARM_FREEZER,
|
||||||
translation_key="alarm_sensor_temp",
|
desc="Temperature Alarm Freezer",
|
||||||
state_key=REFRIGERATION_EVENT_TEMP_ALARM_FREEZER,
|
|
||||||
appliance_types=("FridgeFreezer", "Freezer"),
|
appliance_types=("FridgeFreezer", "Freezer"),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Bean Container Empty",
|
key=COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
||||||
translation_key="alarm_sensor_coffee_bean_container",
|
desc="Bean Container Empty",
|
||||||
state_key=COFFEE_EVENT_BEAN_CONTAINER_EMPTY,
|
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Water Tank Empty",
|
key=COFFEE_EVENT_WATER_TANK_EMPTY,
|
||||||
translation_key="alarm_sensor_coffee_water_tank",
|
desc="Water Tank Empty",
|
||||||
state_key=COFFEE_EVENT_WATER_TANK_EMPTY,
|
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
HomeConnectSensorEntityDescription(
|
HomeConnectSensorEntityDescription(
|
||||||
key="Drip Tray Full",
|
key=COFFEE_EVENT_DRIP_TRAY_FULL,
|
||||||
translation_key="alarm_sensor_coffee_drip_tray",
|
desc="Drip Tray Full",
|
||||||
state_key=COFFEE_EVENT_DRIP_TRAY_FULL,
|
|
||||||
appliance_types=("CoffeeMaker",),
|
appliance_types=("CoffeeMaker",),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -128,16 +122,15 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
device: HomeConnectDevice,
|
device: HomeConnectDevice,
|
||||||
|
bsh_key: str,
|
||||||
desc: str,
|
desc: str,
|
||||||
key: str,
|
|
||||||
unit: str,
|
unit: str,
|
||||||
icon: str,
|
icon: str,
|
||||||
device_class: SensorDeviceClass,
|
device_class: SensorDeviceClass,
|
||||||
sign: int = 1,
|
sign: int = 1,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, desc)
|
super().__init__(device, bsh_key, desc)
|
||||||
self._key = key
|
|
||||||
self._sign = sign
|
self._sign = sign
|
||||||
self._attr_native_unit_of_measurement = unit
|
self._attr_native_unit_of_measurement = unit
|
||||||
self._attr_icon = icon
|
self._attr_icon = icon
|
||||||
@ -151,10 +144,10 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update the sensor's status."""
|
"""Update the sensor's status."""
|
||||||
status = self.device.appliance.status
|
status = self.device.appliance.status
|
||||||
if self._key not in status:
|
if self.bsh_key not in status:
|
||||||
self._attr_native_value = None
|
self._attr_native_value = None
|
||||||
elif self.device_class == SensorDeviceClass.TIMESTAMP:
|
elif self.device_class == SensorDeviceClass.TIMESTAMP:
|
||||||
if ATTR_VALUE not in status[self._key]:
|
if ATTR_VALUE not in status[self.bsh_key]:
|
||||||
self._attr_native_value = None
|
self._attr_native_value = None
|
||||||
elif (
|
elif (
|
||||||
self._attr_native_value is not None
|
self._attr_native_value is not None
|
||||||
@ -175,13 +168,13 @@ class HomeConnectSensor(HomeConnectEntity, SensorEntity):
|
|||||||
BSH_OPERATION_STATE_FINISHED,
|
BSH_OPERATION_STATE_FINISHED,
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
seconds = self._sign * float(status[self._key][ATTR_VALUE])
|
seconds = self._sign * float(status[self.bsh_key][ATTR_VALUE])
|
||||||
self._attr_native_value = dt_util.utcnow() + timedelta(seconds=seconds)
|
self._attr_native_value = dt_util.utcnow() + timedelta(seconds=seconds)
|
||||||
else:
|
else:
|
||||||
self._attr_native_value = None
|
self._attr_native_value = None
|
||||||
else:
|
else:
|
||||||
self._attr_native_value = status[self._key].get(ATTR_VALUE)
|
self._attr_native_value = status[self.bsh_key].get(ATTR_VALUE)
|
||||||
if self._key == BSH_OPERATION_STATE:
|
if self.bsh_key == BSH_OPERATION_STATE:
|
||||||
# Value comes back as an enum, we only really care about the
|
# Value comes back as an enum, we only really care about the
|
||||||
# last part, so split it off
|
# last part, so split it off
|
||||||
# https://developer.home-connect.com/docs/status/operation_state
|
# https://developer.home-connect.com/docs/status/operation_state
|
||||||
@ -203,7 +196,9 @@ class HomeConnectAlarmSensor(HomeConnectEntity, SensorEntity):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
super().__init__(device, self.entity_description.key)
|
super().__init__(
|
||||||
|
device, self.entity_description.key, self.entity_description.desc
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available(self) -> bool:
|
def available(self) -> bool:
|
||||||
@ -213,7 +208,7 @@ class HomeConnectAlarmSensor(HomeConnectEntity, SensorEntity):
|
|||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update the sensor's status."""
|
"""Update the sensor's status."""
|
||||||
self._attr_native_value = (
|
self._attr_native_value = (
|
||||||
self.device.appliance.status.get(self.entity_description.state_key, {})
|
self.device.appliance.status.get(self.bsh_key, {})
|
||||||
.get(ATTR_VALUE, BSH_EVENT_PRESENT_STATE_OFF)
|
.get(ATTR_VALUE, BSH_EVENT_PRESENT_STATE_OFF)
|
||||||
.rsplit(".", maxsplit=1)[-1]
|
.rsplit(".", maxsplit=1)[-1]
|
||||||
.lower()
|
.lower()
|
||||||
|
@ -34,22 +34,21 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class HomeConnectSwitchEntityDescription(SwitchEntityDescription):
|
class HomeConnectSwitchEntityDescription(SwitchEntityDescription):
|
||||||
"""Switch entity description."""
|
"""Switch entity description."""
|
||||||
|
|
||||||
on_key: str
|
desc: str
|
||||||
|
|
||||||
|
|
||||||
SWITCHES: tuple[HomeConnectSwitchEntityDescription, ...] = (
|
SWITCHES: tuple[HomeConnectSwitchEntityDescription, ...] = (
|
||||||
HomeConnectSwitchEntityDescription(
|
HomeConnectSwitchEntityDescription(
|
||||||
key="Supermode Freezer",
|
key=REFRIGERATION_SUPERMODEFREEZER,
|
||||||
on_key=REFRIGERATION_SUPERMODEFREEZER,
|
desc="Supermode Freezer",
|
||||||
),
|
),
|
||||||
HomeConnectSwitchEntityDescription(
|
HomeConnectSwitchEntityDescription(
|
||||||
key="Supermode Refrigerator",
|
key=REFRIGERATION_SUPERMODEREFRIGERATOR,
|
||||||
on_key=REFRIGERATION_SUPERMODEREFRIGERATOR,
|
desc="Supermode Refrigerator",
|
||||||
),
|
),
|
||||||
HomeConnectSwitchEntityDescription(
|
HomeConnectSwitchEntityDescription(
|
||||||
key="Dispenser Enabled",
|
key=REFRIGERATION_DISPENSER,
|
||||||
on_key=REFRIGERATION_DISPENSER,
|
desc="Dispenser Enabled",
|
||||||
translation_key="refrigeration_dispenser",
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -75,7 +74,7 @@ async def async_setup_entry(
|
|||||||
entities.extend(
|
entities.extend(
|
||||||
HomeConnectSwitch(device=hc_device, entity_description=description)
|
HomeConnectSwitch(device=hc_device, entity_description=description)
|
||||||
for description in SWITCHES
|
for description in SWITCHES
|
||||||
if description.on_key in hc_device.appliance.status
|
if description.key in hc_device.appliance.status
|
||||||
)
|
)
|
||||||
|
|
||||||
return entities
|
return entities
|
||||||
@ -96,7 +95,7 @@ class HomeConnectSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
self.entity_description = entity_description
|
self.entity_description = entity_description
|
||||||
self._attr_available = False
|
self._attr_available = False
|
||||||
super().__init__(device=device, desc=entity_description.key)
|
super().__init__(device, entity_description.key, entity_description.desc)
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn on setting."""
|
"""Turn on setting."""
|
||||||
@ -104,7 +103,7 @@ class HomeConnectSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
_LOGGER.debug("Turning on %s", self.entity_description.key)
|
_LOGGER.debug("Turning on %s", self.entity_description.key)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self.entity_description.on_key, True
|
self.device.appliance.set_setting, self.entity_description.key, True
|
||||||
)
|
)
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying to turn on: %s", err)
|
_LOGGER.error("Error while trying to turn on: %s", err)
|
||||||
@ -120,7 +119,7 @@ class HomeConnectSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
_LOGGER.debug("Turning off %s", self.entity_description.key)
|
_LOGGER.debug("Turning off %s", self.entity_description.key)
|
||||||
try:
|
try:
|
||||||
await self.hass.async_add_executor_job(
|
await self.hass.async_add_executor_job(
|
||||||
self.device.appliance.set_setting, self.entity_description.on_key, False
|
self.device.appliance.set_setting, self.entity_description.key, False
|
||||||
)
|
)
|
||||||
except HomeConnectError as err:
|
except HomeConnectError as err:
|
||||||
_LOGGER.error("Error while trying to turn off: %s", err)
|
_LOGGER.error("Error while trying to turn off: %s", err)
|
||||||
@ -134,7 +133,7 @@ class HomeConnectSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
"""Update the switch's status."""
|
"""Update the switch's status."""
|
||||||
|
|
||||||
self._attr_is_on = self.device.appliance.status.get(
|
self._attr_is_on = self.device.appliance.status.get(
|
||||||
self.entity_description.on_key, {}
|
self.entity_description.key, {}
|
||||||
).get(ATTR_VALUE)
|
).get(ATTR_VALUE)
|
||||||
self._attr_available = True
|
self._attr_available = True
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
@ -154,7 +153,7 @@ class HomeConnectProgramSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
desc = " ".join(
|
desc = " ".join(
|
||||||
["Program", program_name.split(".")[-3], program_name.split(".")[-1]]
|
["Program", program_name.split(".")[-3], program_name.split(".")[-1]]
|
||||||
)
|
)
|
||||||
super().__init__(device, desc)
|
super().__init__(device, desc, desc)
|
||||||
self.program_name = program_name
|
self.program_name = program_name
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
@ -192,7 +191,7 @@ class HomeConnectPowerSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
|
|
||||||
def __init__(self, device: HomeConnectDevice) -> None:
|
def __init__(self, device: HomeConnectDevice) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, "Power")
|
super().__init__(device, BSH_POWER_STATE, "Power")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Switch the device on."""
|
"""Switch the device on."""
|
||||||
@ -259,7 +258,7 @@ class HomeConnectChildLockSwitch(HomeConnectEntity, SwitchEntity):
|
|||||||
|
|
||||||
def __init__(self, device: HomeConnectDevice) -> None:
|
def __init__(self, device: HomeConnectDevice) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
super().__init__(device, "ChildLock")
|
super().__init__(device, BSH_CHILD_LOCK_STATE, "ChildLock")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Switch child lock on."""
|
"""Switch child lock on."""
|
||||||
|
@ -67,6 +67,20 @@ def mock_config_entry(token_entry: dict[str, Any]) -> MockConfigEntry:
|
|||||||
"auth_implementation": FAKE_AUTH_IMPL,
|
"auth_implementation": FAKE_AUTH_IMPL,
|
||||||
"token": token_entry,
|
"token": token_entry,
|
||||||
},
|
},
|
||||||
|
minor_version=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="config_entry_v1_1")
|
||||||
|
def mock_config_entry_v1_1(token_entry: dict[str, Any]) -> MockConfigEntry:
|
||||||
|
"""Fixture for a config entry."""
|
||||||
|
return MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
data={
|
||||||
|
"auth_implementation": FAKE_AUTH_IMPL,
|
||||||
|
"token": token_entry,
|
||||||
|
},
|
||||||
|
minor_version=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,18 +2,31 @@
|
|||||||
|
|
||||||
from collections.abc import Awaitable, Callable
|
from collections.abc import Awaitable, Callable
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, Mock
|
from unittest.mock import MagicMock, Mock, patch
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
import requests_mock
|
import requests_mock
|
||||||
|
|
||||||
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||||
from homeassistant.components.home_connect import SCAN_INTERVAL
|
from homeassistant.components.home_connect import SCAN_INTERVAL
|
||||||
from homeassistant.components.home_connect.const import DOMAIN, OAUTH2_TOKEN
|
from homeassistant.components.home_connect.const import (
|
||||||
|
BSH_CHILD_LOCK_STATE,
|
||||||
|
BSH_OPERATION_STATE,
|
||||||
|
BSH_POWER_STATE,
|
||||||
|
BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
|
COOKING_LIGHTING,
|
||||||
|
DOMAIN,
|
||||||
|
OAUTH2_TOKEN,
|
||||||
|
)
|
||||||
|
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN
|
||||||
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
from .conftest import (
|
from .conftest import (
|
||||||
CLIENT_ID,
|
CLIENT_ID,
|
||||||
@ -294,3 +307,68 @@ async def test_services_exception(
|
|||||||
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
await hass.services.async_call(**service_call)
|
await hass.services.async_call(**service_call)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_migration(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
config_entry_v1_1: MockConfigEntry,
|
||||||
|
appliance: Mock,
|
||||||
|
platforms: list[Platform],
|
||||||
|
) -> None:
|
||||||
|
"""Test entity migration."""
|
||||||
|
|
||||||
|
config_entry_v1_1.add_to_hass(hass)
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=config_entry_v1_1.entry_id,
|
||||||
|
identifiers={(DOMAIN, appliance.haId)},
|
||||||
|
)
|
||||||
|
|
||||||
|
test_entities = [
|
||||||
|
(
|
||||||
|
SENSOR_DOMAIN,
|
||||||
|
"Operation State",
|
||||||
|
BSH_OPERATION_STATE,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SWITCH_DOMAIN,
|
||||||
|
"ChildLock",
|
||||||
|
BSH_CHILD_LOCK_STATE,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SWITCH_DOMAIN,
|
||||||
|
"Power",
|
||||||
|
BSH_POWER_STATE,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
BINARY_SENSOR_DOMAIN,
|
||||||
|
"Remote Start",
|
||||||
|
BSH_REMOTE_START_ALLOWANCE_STATE,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
"Light",
|
||||||
|
COOKING_LIGHTING,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
for domain, old_unique_id_suffix, _ in test_entities:
|
||||||
|
entity_registry.async_get_or_create(
|
||||||
|
domain,
|
||||||
|
DOMAIN,
|
||||||
|
f"{appliance.haId}-{old_unique_id_suffix}",
|
||||||
|
device_id=device_entry.id,
|
||||||
|
config_entry=config_entry_v1_1,
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch("homeassistant.components.home_connect.PLATFORMS", platforms):
|
||||||
|
await hass.config_entries.async_setup(config_entry_v1_1.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
for domain, _, expected_unique_id_suffix in test_entities:
|
||||||
|
assert entity_registry.async_get_entity_id(
|
||||||
|
domain, DOMAIN, f"{appliance.haId}-{expected_unique_id_suffix}"
|
||||||
|
)
|
||||||
|
assert config_entry_v1_1.minor_version == 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user