2020-05-05 09:26:14 +00:00
|
|
|
"""Provides a switch for Home Connect."""
|
2024-03-08 18:15:59 +00:00
|
|
|
|
2024-09-05 18:52:12 +00:00
|
|
|
from dataclasses import dataclass
|
2020-05-05 09:26:14 +00:00
|
|
|
import logging
|
2022-08-30 18:55:01 +00:00
|
|
|
from typing import Any
|
2020-05-05 09:26:14 +00:00
|
|
|
|
|
|
|
from homeconnect.api import HomeConnectError
|
|
|
|
|
2024-09-05 18:52:12 +00:00
|
|
|
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
2022-01-03 18:23:11 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2021-02-17 08:44:37 +00:00
|
|
|
from homeassistant.const import CONF_DEVICE, CONF_ENTITIES
|
2022-01-03 18:23:11 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2020-05-05 09:26:14 +00:00
|
|
|
|
2024-09-05 18:52:12 +00:00
|
|
|
from .api import ConfigEntryAuth
|
2020-05-05 09:26:14 +00:00
|
|
|
from .const import (
|
2021-02-17 08:44:37 +00:00
|
|
|
ATTR_VALUE,
|
2020-05-05 09:26:14 +00:00
|
|
|
BSH_ACTIVE_PROGRAM,
|
2024-06-21 11:26:37 +00:00
|
|
|
BSH_CHILD_LOCK_STATE,
|
2020-05-05 09:26:14 +00:00
|
|
|
BSH_OPERATION_STATE,
|
|
|
|
BSH_POWER_ON,
|
|
|
|
BSH_POWER_STATE,
|
|
|
|
DOMAIN,
|
2024-09-05 18:52:12 +00:00
|
|
|
REFRIGERATION_DISPENSER,
|
|
|
|
REFRIGERATION_SUPERMODEFREEZER,
|
|
|
|
REFRIGERATION_SUPERMODEREFRIGERATOR,
|
2020-05-05 09:26:14 +00:00
|
|
|
)
|
2024-09-05 18:52:12 +00:00
|
|
|
from .entity import HomeConnectDevice, HomeConnectEntity
|
2020-05-05 09:26:14 +00:00
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2024-09-05 18:52:12 +00:00
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
|
|
class HomeConnectSwitchEntityDescription(SwitchEntityDescription):
|
|
|
|
"""Switch entity description."""
|
|
|
|
|
|
|
|
on_key: str
|
|
|
|
|
|
|
|
|
|
|
|
SWITCHES: tuple[HomeConnectSwitchEntityDescription, ...] = (
|
|
|
|
HomeConnectSwitchEntityDescription(
|
|
|
|
key="Supermode Freezer",
|
|
|
|
on_key=REFRIGERATION_SUPERMODEFREEZER,
|
|
|
|
),
|
|
|
|
HomeConnectSwitchEntityDescription(
|
|
|
|
key="Supermode Refrigerator",
|
|
|
|
on_key=REFRIGERATION_SUPERMODEREFRIGERATOR,
|
|
|
|
),
|
|
|
|
HomeConnectSwitchEntityDescription(
|
|
|
|
key="Dispenser Enabled",
|
|
|
|
on_key=REFRIGERATION_DISPENSER,
|
|
|
|
translation_key="refrigeration_dispenser",
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-01-03 18:23:11 +00:00
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Set up the Home Connect switch."""
|
|
|
|
|
|
|
|
def get_entities():
|
|
|
|
"""Get a list of entities."""
|
|
|
|
entities = []
|
2024-09-05 18:52:12 +00:00
|
|
|
hc_api: ConfigEntryAuth = hass.data[DOMAIN][config_entry.entry_id]
|
2020-05-05 09:26:14 +00:00
|
|
|
for device_dict in hc_api.devices:
|
2021-02-17 08:44:37 +00:00
|
|
|
entity_dicts = device_dict.get(CONF_ENTITIES, {}).get("switch", [])
|
2020-05-05 09:26:14 +00:00
|
|
|
entity_list = [HomeConnectProgramSwitch(**d) for d in entity_dicts]
|
2021-02-17 08:44:37 +00:00
|
|
|
entity_list += [HomeConnectPowerSwitch(device_dict[CONF_DEVICE])]
|
2024-06-21 11:26:37 +00:00
|
|
|
entity_list += [HomeConnectChildLockSwitch(device_dict[CONF_DEVICE])]
|
2024-09-05 18:52:12 +00:00
|
|
|
# Auto-discover entities
|
|
|
|
hc_device: HomeConnectDevice = device_dict[CONF_DEVICE]
|
|
|
|
entities.extend(
|
|
|
|
HomeConnectSwitch(device=hc_device, entity_description=description)
|
|
|
|
for description in SWITCHES
|
|
|
|
if description.on_key in hc_device.appliance.status
|
|
|
|
)
|
|
|
|
entities.extend(entity_list)
|
|
|
|
|
2020-05-05 09:26:14 +00:00
|
|
|
return entities
|
|
|
|
|
|
|
|
async_add_entities(await hass.async_add_executor_job(get_entities), True)
|
|
|
|
|
|
|
|
|
2024-09-05 18:52:12 +00:00
|
|
|
class HomeConnectSwitch(HomeConnectEntity, SwitchEntity):
|
|
|
|
"""Generic switch class for Home Connect Binary Settings."""
|
|
|
|
|
|
|
|
entity_description: HomeConnectSwitchEntityDescription
|
|
|
|
_attr_available: bool = False
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
device: HomeConnectDevice,
|
|
|
|
entity_description: HomeConnectSwitchEntityDescription,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize the entity."""
|
|
|
|
self.entity_description = entity_description
|
|
|
|
super().__init__(device=device, desc=entity_description.key)
|
|
|
|
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn on setting."""
|
|
|
|
|
|
|
|
_LOGGER.debug("Turning on %s", self.entity_description.key)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.set_setting, self.entity_description.on_key, True
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to turn on: %s", err)
|
|
|
|
self._attr_available = False
|
|
|
|
return
|
|
|
|
|
|
|
|
self._attr_available = True
|
|
|
|
self.async_entity_update()
|
|
|
|
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
|
|
"""Turn off setting."""
|
|
|
|
|
|
|
|
_LOGGER.debug("Turning off %s", self.entity_description.key)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.set_setting, self.entity_description.on_key, False
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to turn off: %s", err)
|
|
|
|
self._attr_available = False
|
|
|
|
return
|
|
|
|
|
|
|
|
self._attr_available = True
|
|
|
|
self.async_entity_update()
|
|
|
|
|
|
|
|
async def async_update(self) -> None:
|
|
|
|
"""Update the switch's status."""
|
|
|
|
|
|
|
|
self._attr_is_on = self.device.appliance.status.get(
|
|
|
|
self.entity_description.on_key, {}
|
|
|
|
).get(ATTR_VALUE)
|
|
|
|
self._attr_available = True
|
|
|
|
_LOGGER.debug(
|
|
|
|
"Updated %s, new state: %s",
|
|
|
|
self.entity_description.key,
|
|
|
|
self._attr_is_on,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2020-05-05 09:26:14 +00:00
|
|
|
class HomeConnectProgramSwitch(HomeConnectEntity, SwitchEntity):
|
|
|
|
"""Switch class for Home Connect."""
|
|
|
|
|
|
|
|
def __init__(self, device, program_name):
|
|
|
|
"""Initialize the entity."""
|
|
|
|
desc = " ".join(["Program", program_name.split(".")[-1]])
|
2023-04-30 16:50:51 +00:00
|
|
|
if device.appliance.type == "WasherDryer":
|
|
|
|
desc = " ".join(
|
|
|
|
["Program", program_name.split(".")[-3], program_name.split(".")[-1]]
|
|
|
|
)
|
2020-05-05 09:26:14 +00:00
|
|
|
super().__init__(device, desc)
|
|
|
|
self.program_name = program_name
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Start the program."""
|
|
|
|
_LOGGER.debug("Tried to turn on program %s", self.program_name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.start_program, self.program_name
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to start program: %s", err)
|
|
|
|
self.async_entity_update()
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Stop the program."""
|
|
|
|
_LOGGER.debug("Tried to stop program %s", self.program_name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(self.device.appliance.stop_program)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to stop program: %s", err)
|
|
|
|
self.async_entity_update()
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_update(self) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Update the switch's status."""
|
|
|
|
state = self.device.appliance.status.get(BSH_ACTIVE_PROGRAM, {})
|
2021-02-17 08:44:37 +00:00
|
|
|
if state.get(ATTR_VALUE) == self.program_name:
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = True
|
2020-05-05 09:26:14 +00:00
|
|
|
else:
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = False
|
|
|
|
_LOGGER.debug("Updated, new state: %s", self._attr_is_on)
|
2020-05-05 09:26:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
class HomeConnectPowerSwitch(HomeConnectEntity, SwitchEntity):
|
|
|
|
"""Power switch class for Home Connect."""
|
|
|
|
|
|
|
|
def __init__(self, device):
|
2024-03-25 10:33:00 +00:00
|
|
|
"""Initialize the entity."""
|
2020-05-05 09:26:14 +00:00
|
|
|
super().__init__(device, "Power")
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Switch the device on."""
|
|
|
|
_LOGGER.debug("Tried to switch on %s", self.name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
2021-02-17 08:44:37 +00:00
|
|
|
self.device.appliance.set_setting, BSH_POWER_STATE, BSH_POWER_ON
|
2020-05-05 09:26:14 +00:00
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to turn on device: %s", err)
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = False
|
2020-05-05 09:26:14 +00:00
|
|
|
self.async_entity_update()
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Switch the device off."""
|
|
|
|
_LOGGER.debug("tried to switch off %s", self.name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.set_setting,
|
|
|
|
BSH_POWER_STATE,
|
|
|
|
self.device.power_off_state,
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to turn off device: %s", err)
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = True
|
2020-05-05 09:26:14 +00:00
|
|
|
self.async_entity_update()
|
|
|
|
|
2022-08-30 18:55:01 +00:00
|
|
|
async def async_update(self) -> None:
|
2020-05-05 09:26:14 +00:00
|
|
|
"""Update the switch's status."""
|
|
|
|
if (
|
2021-02-17 08:44:37 +00:00
|
|
|
self.device.appliance.status.get(BSH_POWER_STATE, {}).get(ATTR_VALUE)
|
2020-05-05 09:26:14 +00:00
|
|
|
== BSH_POWER_ON
|
|
|
|
):
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = True
|
2020-05-05 09:26:14 +00:00
|
|
|
elif (
|
2021-02-17 08:44:37 +00:00
|
|
|
self.device.appliance.status.get(BSH_POWER_STATE, {}).get(ATTR_VALUE)
|
2020-05-05 09:26:14 +00:00
|
|
|
== self.device.power_off_state
|
|
|
|
):
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = False
|
2020-05-05 09:26:14 +00:00
|
|
|
elif self.device.appliance.status.get(BSH_OPERATION_STATE, {}).get(
|
2021-02-17 08:44:37 +00:00
|
|
|
ATTR_VALUE, None
|
2020-05-05 09:26:14 +00:00
|
|
|
) in [
|
|
|
|
"BSH.Common.EnumType.OperationState.Ready",
|
|
|
|
"BSH.Common.EnumType.OperationState.DelayedStart",
|
|
|
|
"BSH.Common.EnumType.OperationState.Run",
|
|
|
|
"BSH.Common.EnumType.OperationState.Pause",
|
|
|
|
"BSH.Common.EnumType.OperationState.ActionRequired",
|
|
|
|
"BSH.Common.EnumType.OperationState.Aborting",
|
|
|
|
"BSH.Common.EnumType.OperationState.Finished",
|
|
|
|
]:
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = True
|
2020-05-05 09:26:14 +00:00
|
|
|
elif (
|
2021-02-17 08:44:37 +00:00
|
|
|
self.device.appliance.status.get(BSH_OPERATION_STATE, {}).get(ATTR_VALUE)
|
2020-05-05 09:26:14 +00:00
|
|
|
== "BSH.Common.EnumType.OperationState.Inactive"
|
|
|
|
):
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = False
|
2020-05-05 09:26:14 +00:00
|
|
|
else:
|
2023-09-04 07:15:25 +00:00
|
|
|
self._attr_is_on = None
|
|
|
|
_LOGGER.debug("Updated, new state: %s", self._attr_is_on)
|
2024-06-21 11:26:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
class HomeConnectChildLockSwitch(HomeConnectEntity, SwitchEntity):
|
|
|
|
"""Child lock switch class for Home Connect."""
|
|
|
|
|
|
|
|
def __init__(self, device) -> None:
|
|
|
|
"""Initialize the entity."""
|
|
|
|
super().__init__(device, "ChildLock")
|
|
|
|
|
|
|
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
|
|
"""Switch child lock on."""
|
|
|
|
_LOGGER.debug("Tried to switch child lock on device: %s", self.name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.set_setting, BSH_CHILD_LOCK_STATE, True
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error("Error while trying to turn on child lock on device: %s", err)
|
|
|
|
self._attr_is_on = False
|
|
|
|
self.async_entity_update()
|
|
|
|
|
|
|
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
|
|
"""Switch child lock off."""
|
|
|
|
_LOGGER.debug("Tried to switch off child lock on device: %s", self.name)
|
|
|
|
try:
|
|
|
|
await self.hass.async_add_executor_job(
|
|
|
|
self.device.appliance.set_setting, BSH_CHILD_LOCK_STATE, False
|
|
|
|
)
|
|
|
|
except HomeConnectError as err:
|
|
|
|
_LOGGER.error(
|
|
|
|
"Error while trying to turn off child lock on device: %s", err
|
|
|
|
)
|
|
|
|
self._attr_is_on = True
|
|
|
|
self.async_entity_update()
|
|
|
|
|
|
|
|
async def async_update(self) -> None:
|
|
|
|
"""Update the switch's status."""
|
|
|
|
self._attr_is_on = False
|
|
|
|
if self.device.appliance.status.get(BSH_CHILD_LOCK_STATE, {}).get(ATTR_VALUE):
|
|
|
|
self._attr_is_on = True
|
|
|
|
_LOGGER.debug("Updated child lock, new state: %s", self._attr_is_on)
|