core/homeassistant/components/vicare/button.py

141 lines
4.4 KiB
Python

"""Viessmann ViCare button device."""
from __future__ import annotations
from contextlib import suppress
from dataclasses import dataclass
import logging
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
PyViCareNotSupportedFeatureError,
PyViCareRateLimitError,
)
import requests
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ViCareRequiredKeysMixinWithSet
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG, VICARE_NAME
_LOGGER = logging.getLogger(__name__)
BUTTON_DHW_ACTIVATE_ONETIME_CHARGE = "activate_onetimecharge"
@dataclass
class ViCareButtonEntityDescription(
ButtonEntityDescription, ViCareRequiredKeysMixinWithSet
):
"""Describes ViCare button entity."""
BUTTON_DESCRIPTIONS: tuple[ViCareButtonEntityDescription, ...] = (
ViCareButtonEntityDescription(
key=BUTTON_DHW_ACTIVATE_ONETIME_CHARGE,
name="Activate one-time charge",
icon="mdi:shower-head",
entity_category=EntityCategory.CONFIG,
value_getter=lambda api: api.getOneTimeCharge(),
value_setter=lambda api: api.activateOneTimeCharge(),
),
)
def _build_entity(name, vicare_api, device_config, description):
"""Create a ViCare button entity."""
_LOGGER.debug("Found device %s", name)
try:
description.value_getter(vicare_api)
_LOGGER.debug("Found entity %s", name)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("Feature not supported %s", name)
return None
except AttributeError:
_LOGGER.debug("Attribute Error %s", name)
return None
return ViCareButton(
name,
vicare_api,
device_config,
description,
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Create the ViCare button entities."""
name = VICARE_NAME
api = hass.data[DOMAIN][config_entry.entry_id][VICARE_API]
entities = []
for description in BUTTON_DESCRIPTIONS:
entity = await hass.async_add_executor_job(
_build_entity,
f"{name} {description.name}",
api,
hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG],
description,
)
if entity is not None:
entities.append(entity)
async_add_entities(entities)
class ViCareButton(ButtonEntity):
"""Representation of a ViCare button."""
entity_description: ViCareButtonEntityDescription
def __init__(
self, name, api, device_config, description: ViCareButtonEntityDescription
) -> None:
"""Initialize the button."""
self.entity_description = description
self._device_config = device_config
self._api = api
def press(self) -> None:
"""Handle the button press."""
try:
with suppress(PyViCareNotSupportedFeatureError):
self.entity_description.value_setter(self._api)
except requests.exceptions.ConnectionError:
_LOGGER.error("Unable to retrieve data from ViCare server")
except ValueError:
_LOGGER.error("Unable to decode data from ViCare server")
except PyViCareRateLimitError as limit_exception:
_LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception)
except PyViCareInvalidDataError as invalid_data_exception:
_LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception)
@property
def device_info(self) -> DeviceInfo:
"""Return device info for this device."""
return DeviceInfo(
identifiers={(DOMAIN, self._device_config.getConfig().serial)},
name=self._device_config.getModel(),
manufacturer="Viessmann",
model=self._device_config.getModel(),
configuration_url="https://developer.viessmann.com/",
)
@property
def unique_id(self) -> str:
"""Return unique ID for this device."""
tmp_id = (
f"{self._device_config.getConfig().serial}-{self.entity_description.key}"
)
if hasattr(self._api, "id"):
return f"{tmp_id}-{self._api.id}"
return tmp_id