From b617451a258e88377f7fa664cef7f8acec0aa4f8 Mon Sep 17 00:00:00 2001 From: Simone Chemelli Date: Wed, 27 Sep 2023 00:09:42 +0200 Subject: [PATCH] Add button platform to Vodafone Station (#100941) * button platform initial commit * fix is_suitable * cleanup * coveragerc * add translations * remove redundant key --- .coveragerc | 1 + .../components/vodafone_station/__init__.py | 2 +- .../components/vodafone_station/button.py | 113 ++++++++++++++++++ .../vodafone_station/coordinator.py | 20 ++++ .../components/vodafone_station/sensor.py | 17 +-- .../components/vodafone_station/strings.json | 5 + 6 files changed, 142 insertions(+), 16 deletions(-) create mode 100644 homeassistant/components/vodafone_station/button.py diff --git a/.coveragerc b/.coveragerc index fe53d976bf6..f6f76f5db51 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1480,6 +1480,7 @@ omit = homeassistant/components/vlc_telnet/__init__.py homeassistant/components/vlc_telnet/media_player.py homeassistant/components/vodafone_station/__init__.py + homeassistant/components/vodafone_station/button.py homeassistant/components/vodafone_station/const.py homeassistant/components/vodafone_station/coordinator.py homeassistant/components/vodafone_station/device_tracker.py diff --git a/homeassistant/components/vodafone_station/__init__.py b/homeassistant/components/vodafone_station/__init__.py index cf2a22d2dbc..816e9241739 100644 --- a/homeassistant/components/vodafone_station/__init__.py +++ b/homeassistant/components/vodafone_station/__init__.py @@ -7,7 +7,7 @@ from homeassistant.core import HomeAssistant from .const import DOMAIN from .coordinator import VodafoneStationRouter -PLATFORMS = [Platform.DEVICE_TRACKER, Platform.SENSOR] +PLATFORMS = [Platform.DEVICE_TRACKER, Platform.SENSOR, Platform.BUTTON] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: diff --git a/homeassistant/components/vodafone_station/button.py b/homeassistant/components/vodafone_station/button.py new file mode 100644 index 00000000000..7f93f8023ef --- /dev/null +++ b/homeassistant/components/vodafone_station/button.py @@ -0,0 +1,113 @@ +"""Vodafone Station buttons.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any, Final + +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import _LOGGER, DOMAIN +from .coordinator import VodafoneStationRouter + + +@dataclass +class VodafoneStationBaseEntityDescriptionMixin: + """Mixin to describe a Button entity.""" + + press_action: Callable[[VodafoneStationRouter], Any] + is_suitable: Callable[[dict], bool] + + +@dataclass +class VodafoneStationEntityDescription( + ButtonEntityDescription, VodafoneStationBaseEntityDescriptionMixin +): + """Vodafone Station entity description.""" + + +BUTTON_TYPES: Final = ( + VodafoneStationEntityDescription( + key="reboot", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + press_action=lambda coordinator: coordinator.api.restart_router(), + is_suitable=lambda _: True, + ), + VodafoneStationEntityDescription( + key="dsl_ready", + translation_key="dsl_reconnect", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.DIAGNOSTIC, + press_action=lambda coordinator: coordinator.api.restart_connection("dsl"), + is_suitable=lambda info: info.get("dsl_ready") == "1", + ), + VodafoneStationEntityDescription( + key="fiber_ready", + translation_key="fiber_reconnect", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.DIAGNOSTIC, + press_action=lambda coordinator: coordinator.api.restart_connection("fiber"), + is_suitable=lambda info: info.get("fiber_ready") == "1", + ), + VodafoneStationEntityDescription( + key="vf_internet_key_online_since", + translation_key="internet_key_reconnect", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.DIAGNOSTIC, + press_action=lambda coordinator: coordinator.api.restart_connection( + "internet_key" + ), + is_suitable=lambda info: info.get("vf_internet_key_online_since") != "", + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up entry.""" + _LOGGER.debug("Setting up Vodafone Station buttons") + + coordinator: VodafoneStationRouter = hass.data[DOMAIN][entry.entry_id] + + sensors_data = coordinator.data.sensors + + async_add_entities( + VodafoneStationSensorEntity(coordinator, sensor_descr) + for sensor_descr in BUTTON_TYPES + if sensor_descr.is_suitable(sensors_data) + ) + + +class VodafoneStationSensorEntity( + CoordinatorEntity[VodafoneStationRouter], ButtonEntity +): + """Representation of a Vodafone Station button.""" + + _attr_has_entity_name = True + entity_description: VodafoneStationEntityDescription + + def __init__( + self, + coordinator: VodafoneStationRouter, + description: VodafoneStationEntityDescription, + ) -> None: + """Initialize a Vodafone Station sensor.""" + super().__init__(coordinator) + self.entity_description = description + self._attr_device_info = coordinator.device_info + self._attr_unique_id = f"{coordinator.serial_number}_{description.key}" + + async def async_press(self) -> None: + """Triggers the Shelly button press service.""" + await self.entity_description.press_action(self.coordinator) diff --git a/homeassistant/components/vodafone_station/coordinator.py b/homeassistant/components/vodafone_station/coordinator.py index 58079180bf8..fe1ff1889d5 100644 --- a/homeassistant/components/vodafone_station/coordinator.py +++ b/homeassistant/components/vodafone_station/coordinator.py @@ -8,6 +8,7 @@ from aiovodafone import VodafoneStationApi, VodafoneStationDevice, exceptions from homeassistant.components.device_tracker import DEFAULT_CONSIDER_HOME from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.util import dt as dt_util @@ -122,3 +123,22 @@ class VodafoneStationRouter(DataUpdateCoordinator[UpdateCoordinatorDataType]): def signal_device_new(self) -> str: """Event specific per Vodafone Station entry to signal new device.""" return f"{DOMAIN}-device-new-{self._id}" + + @property + def serial_number(self) -> str: + """Device serial number.""" + return self.data.sensors["sys_serial_number"] + + @property + def device_info(self) -> DeviceInfo: + """Set device info.""" + sensors_data = self.data.sensors + return DeviceInfo( + configuration_url=self.api.base_url, + identifiers={(DOMAIN, self.serial_number)}, + name=f"Vodafone Station ({self.serial_number})", + manufacturer="Vodafone", + model=sensors_data.get("sys_model_name"), + hw_version=sensors_data["sys_hardware_version"], + sw_version=sensors_data["sys_firmware_version"], + ) diff --git a/homeassistant/components/vodafone_station/sensor.py b/homeassistant/components/vodafone_station/sensor.py index 0ca705ad56b..ce2d3154de3 100644 --- a/homeassistant/components/vodafone_station/sensor.py +++ b/homeassistant/components/vodafone_station/sensor.py @@ -14,7 +14,6 @@ from homeassistant.components.sensor import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfDataRate from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -193,21 +192,9 @@ class VodafoneStationSensorEntity( ) -> None: """Initialize a Vodafone Station sensor.""" super().__init__(coordinator) - - sensors_data = coordinator.data.sensors - serial_num = sensors_data["sys_serial_number"] self.entity_description = description - - self._attr_device_info = DeviceInfo( - configuration_url=coordinator.api.base_url, - identifiers={(DOMAIN, serial_num)}, - name=f"Vodafone Station ({serial_num})", - manufacturer="Vodafone", - model=sensors_data.get("sys_model_name"), - hw_version=sensors_data["sys_hardware_version"], - sw_version=sensors_data["sys_firmware_version"], - ) - self._attr_unique_id = f"{serial_num}_{description.key}" + self._attr_device_info = coordinator.device_info + self._attr_unique_id = f"{coordinator.serial_number}_{description.key}" @property def native_value(self) -> StateType: diff --git a/homeassistant/components/vodafone_station/strings.json b/homeassistant/components/vodafone_station/strings.json index d0dcb46fd10..aaaa27a3614 100644 --- a/homeassistant/components/vodafone_station/strings.json +++ b/homeassistant/components/vodafone_station/strings.json @@ -34,6 +34,11 @@ } }, "entity": { + "button": { + "dsl_reconnect": { "name": "DSL reconnect" }, + "fiber_reconnect": { "name": "Fiber reconnect" }, + "internet_key_reconnect": { "name": "Internet key reconnect" } + }, "sensor": { "external_ipv4": { "name": "WAN IPv4 address" }, "external_ipv6": { "name": "WAN IPv6 address" },