Add buttons and deprecate services for Fritz (#61483)

* Add buttons and deprecate services

* Exclude tests

* Log full service name
This commit is contained in:
Simone Chemelli 2021-12-16 13:25:06 +01:00 committed by GitHub
parent 116759f2a1
commit 105ad861bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 128 additions and 1 deletions

View file

@ -371,6 +371,7 @@ omit =
homeassistant/components/freebox/switch.py
homeassistant/components/fritz/__init__.py
homeassistant/components/fritz/binary_sensor.py
homeassistant/components/fritz/button.py
homeassistant/components/fritz/common.py
homeassistant/components/fritz/const.py
homeassistant/components/fritz/device_tracker.py

View file

@ -0,0 +1,100 @@
"""Switches for AVM Fritz!Box buttons."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import logging
from typing import Final
from homeassistant.components.button import (
ButtonDeviceClass,
ButtonEntity,
ButtonEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ENTITY_CATEGORY_CONFIG
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import slugify
from .common import FritzBoxTools
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
@dataclass
class FritzButtonDescriptionMixin:
"""Mixin to describe a Button entity."""
press_action: Callable
@dataclass
class FritzButtonDescription(ButtonEntityDescription, FritzButtonDescriptionMixin):
"""Class to describe a Button entity."""
BUTTONS: Final = [
FritzButtonDescription(
key="firmware_update",
name="Firmware Update",
device_class=ButtonDeviceClass.UPDATE,
entity_category=ENTITY_CATEGORY_CONFIG,
press_action=lambda router: router.async_trigger_firmware_update(),
),
FritzButtonDescription(
key="reboot",
name="Reboot",
device_class=ButtonDeviceClass.RESTART,
entity_category=ENTITY_CATEGORY_CONFIG,
press_action=lambda router: router.async_trigger_reboot(),
),
FritzButtonDescription(
key="reconnect",
name="Reconnect",
device_class=ButtonDeviceClass.RESTART,
entity_category=ENTITY_CATEGORY_CONFIG,
press_action=lambda router: router.async_trigger_reconnect(),
),
]
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set buttons for device."""
_LOGGER.debug("Setting up buttons")
router: FritzBoxTools = hass.data[DOMAIN][entry.entry_id]
async_add_entities([FritzButton(router, entry.title, button) for button in BUTTONS])
class FritzButton(ButtonEntity):
"""Defines a Fritz!Box base button."""
entity_description: FritzButtonDescription
def __init__(
self,
router: FritzBoxTools,
device_friendly_name: str,
description: FritzButtonDescription,
) -> None:
"""Initialize Fritz!Box button."""
self.entity_description = description
self.router = router
self._attr_name = f"{device_friendly_name} {description.name}"
self._attr_unique_id = slugify(self._attr_name)
self._attr_device_info = DeviceInfo(
connections={(CONNECTION_NETWORK_MAC, router.mac)}
)
async def async_press(self) -> None:
"""Triggers Fritz!Box service."""
await self.entity_description.press_action(self.router)

View file

@ -6,7 +6,7 @@ from dataclasses import dataclass, field
from datetime import datetime, timedelta
import logging
from types import MappingProxyType
from typing import Any, TypedDict
from typing import Any, TypedDict, cast
from fritzconnection import FritzConnection
from fritzconnection.core.exceptions import (
@ -315,6 +315,25 @@ class FritzBoxTools(update_coordinator.DataUpdateCoordinator):
_LOGGER.debug("Checking host info for FRITZ!Box router %s", self.host)
self._update_available, self._latest_firmware = self._update_device_info()
async def async_trigger_firmware_update(self) -> bool:
"""Trigger firmware update."""
results = await self.hass.async_add_executor_job(
self.connection.call_action, "UserInterface:1", "X_AVM-DE_DoUpdate"
)
return cast(bool, results["NewX_AVM-DE_UpdateState"])
async def async_trigger_reboot(self) -> None:
"""Trigger device reboot."""
await self.hass.async_add_executor_job(
self.connection.call_action, "DeviceConfig1", "Reboot"
)
async def async_trigger_reconnect(self) -> None:
"""Trigger device reconnect."""
await self.hass.async_add_executor_job(
self.connection.call_action, "WANIPConn1", "ForceTermination"
)
async def service_fritzbox(
self, service_call: ServiceCall, config_entry: ConfigEntry
) -> None:
@ -326,12 +345,18 @@ class FritzBoxTools(update_coordinator.DataUpdateCoordinator):
try:
if service_call.service == SERVICE_REBOOT:
_LOGGER.warning(
'Service "fritz.reboot" is deprecated, please use the corresponding button entity instead'
)
await self.hass.async_add_executor_job(
self.connection.call_action, "DeviceConfig1", "Reboot"
)
return
if service_call.service == SERVICE_RECONNECT:
_LOGGER.warning(
'Service "fritz.reconnect" is deprecated, please use the corresponding button entity instead'
)
await self.hass.async_add_executor_job(
self.connection.call_action,
"WANIPConn1",

View file

@ -7,6 +7,7 @@ from homeassistant.const import Platform
DOMAIN = "fritz"
PLATFORMS = [
Platform.BUTTON,
Platform.BINARY_SENSOR,
Platform.DEVICE_TRACKER,
Platform.SENSOR,