diff --git a/.coveragerc b/.coveragerc index a419628d50a..d5c9f48ee47 100644 --- a/.coveragerc +++ b/.coveragerc @@ -779,6 +779,7 @@ omit = homeassistant/components/nest/legacy/* homeassistant/components/netdata/sensor.py homeassistant/components/netgear/__init__.py + homeassistant/components/netgear/button.py homeassistant/components/netgear/device_tracker.py homeassistant/components/netgear/router.py homeassistant/components/netgear/sensor.py diff --git a/homeassistant/components/netgear/button.py b/homeassistant/components/netgear/button.py new file mode 100644 index 00000000000..e14600ff52b --- /dev/null +++ b/homeassistant/components/netgear/button.py @@ -0,0 +1,82 @@ +"""Support for Netgear Button.""" +from collections.abc import Callable, Coroutine +from dataclasses import dataclass +from typing import Any + +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator + +from .const import DOMAIN, KEY_COORDINATOR, KEY_ROUTER +from .router import NetgearRouter, NetgearRouterEntity + + +@dataclass +class NetgearButtonEntityDescriptionRequired: + """Required attributes of NetgearButtonEntityDescription.""" + + action: Callable[[NetgearRouter], Callable[[], Coroutine[Any, Any, None]]] + + +@dataclass +class NetgearButtonEntityDescription( + ButtonEntityDescription, NetgearButtonEntityDescriptionRequired +): + """Class describing Netgear button entities.""" + + +BUTTONS = [ + NetgearButtonEntityDescription( + key="reboot", + name="Reboot", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + action=lambda router: router.async_reboot, + ) +] + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up button for Netgear component.""" + router = hass.data[DOMAIN][entry.entry_id][KEY_ROUTER] + coordinator = hass.data[DOMAIN][entry.entry_id][KEY_COORDINATOR] + async_add_entities( + NetgearRouterButtonEntity(coordinator, router, entity_description) + for entity_description in BUTTONS + ) + + +class NetgearRouterButtonEntity(NetgearRouterEntity, ButtonEntity): + """Netgear Router button entity.""" + + entity_description: NetgearButtonEntityDescription + + def __init__( + self, + coordinator: DataUpdateCoordinator, + router: NetgearRouter, + entity_description: NetgearButtonEntityDescription, + ) -> None: + """Initialize a Netgear device.""" + super().__init__(coordinator, router) + self.entity_description = entity_description + self._name = f"{router.device_name} {entity_description.name}" + self._unique_id = f"{router.serial_number}-{entity_description.key}" + + async def async_press(self) -> None: + """Triggers the button press service.""" + async_action = self.entity_description.action(self._router) + await async_action() + + @callback + def async_update_device(self) -> None: + """Update the Netgear device.""" diff --git a/homeassistant/components/netgear/const.py b/homeassistant/components/netgear/const.py index d366ae39961..f2e0263a4e4 100644 --- a/homeassistant/components/netgear/const.py +++ b/homeassistant/components/netgear/const.py @@ -5,7 +5,7 @@ from homeassistant.const import Platform DOMAIN = "netgear" -PLATFORMS = [Platform.DEVICE_TRACKER, Platform.SENSOR, Platform.SWITCH] +PLATFORMS = [Platform.BUTTON, Platform.DEVICE_TRACKER, Platform.SENSOR, Platform.SWITCH] CONF_CONSIDER_HOME = "consider_home" diff --git a/homeassistant/components/netgear/router.py b/homeassistant/components/netgear/router.py index 3778c36d81a..9e44495aa62 100644 --- a/homeassistant/components/netgear/router.py +++ b/homeassistant/components/netgear/router.py @@ -209,6 +209,11 @@ class NetgearRouter: self._api.allow_block_device, mac, allow_block ) + async def async_reboot(self) -> None: + """Reboot the router.""" + async with self._api_lock: + await self.hass.async_add_executor_job(self._api.reboot) + @property def port(self) -> int: """Port used by the API."""