mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 18:27:09 +00:00
Make the network device tracking feature optional in AVM Fritz!Tools (#144149)
* make the network device tracking feature optional * fix doc strings * Apply suggestions from code review Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com> --------- Co-authored-by: Jan Bouwhuis <jbouwh@users.noreply.github.com>
This commit is contained in:
parent
aea5760424
commit
fb94f8ea18
@ -15,6 +15,8 @@ from homeassistant.helpers import config_validation as cv
|
|||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
DEFAULT_SSL,
|
DEFAULT_SSL,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
FRITZ_AUTH_EXCEPTIONS,
|
FRITZ_AUTH_EXCEPTIONS,
|
||||||
@ -38,6 +40,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
async def async_setup_entry(hass: HomeAssistant, entry: FritzConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: FritzConfigEntry) -> bool:
|
||||||
"""Set up fritzboxtools from config entry."""
|
"""Set up fritzboxtools from config entry."""
|
||||||
_LOGGER.debug("Setting up FRITZ!Box Tools component")
|
_LOGGER.debug("Setting up FRITZ!Box Tools component")
|
||||||
|
|
||||||
avm_wrapper = AvmWrapper(
|
avm_wrapper = AvmWrapper(
|
||||||
hass=hass,
|
hass=hass,
|
||||||
config_entry=entry,
|
config_entry=entry,
|
||||||
@ -46,6 +49,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: FritzConfigEntry) -> boo
|
|||||||
username=entry.data[CONF_USERNAME],
|
username=entry.data[CONF_USERNAME],
|
||||||
password=entry.data[CONF_PASSWORD],
|
password=entry.data[CONF_PASSWORD],
|
||||||
use_tls=entry.data.get(CONF_SSL, DEFAULT_SSL),
|
use_tls=entry.data.get(CONF_SSL, DEFAULT_SSL),
|
||||||
|
device_discovery_enabled=entry.options.get(
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING, DEFAULT_CONF_FEATURE_DEVICE_TRACKING
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -62,6 +68,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: FritzConfigEntry) -> boo
|
|||||||
raise ConfigEntryAuthFailed("Missing UPnP configuration")
|
raise ConfigEntryAuthFailed("Missing UPnP configuration")
|
||||||
|
|
||||||
await avm_wrapper.async_config_entry_first_refresh()
|
await avm_wrapper.async_config_entry_first_refresh()
|
||||||
|
await avm_wrapper.async_trigger_cleanup()
|
||||||
|
|
||||||
entry.runtime_data = avm_wrapper
|
entry.runtime_data = avm_wrapper
|
||||||
|
|
||||||
|
@ -35,7 +35,9 @@ from homeassistant.helpers.service_info.ssdp import (
|
|||||||
from homeassistant.helpers.typing import VolDictType
|
from homeassistant.helpers.typing import VolDictType
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
CONF_OLD_DISCOVERY,
|
CONF_OLD_DISCOVERY,
|
||||||
|
DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
DEFAULT_CONF_OLD_DISCOVERY,
|
DEFAULT_CONF_OLD_DISCOVERY,
|
||||||
DEFAULT_HOST,
|
DEFAULT_HOST,
|
||||||
DEFAULT_HTTP_PORT,
|
DEFAULT_HTTP_PORT,
|
||||||
@ -72,7 +74,8 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
"""Initialize FRITZ!Box Tools flow."""
|
"""Initialize FRITZ!Box Tools flow."""
|
||||||
self._name: str = ""
|
self._name: str = ""
|
||||||
self._password: str = ""
|
self._password: str = ""
|
||||||
self._use_tls: bool = False
|
self._use_tls: bool = DEFAULT_SSL
|
||||||
|
self._feature_device_discovery: bool = DEFAULT_CONF_FEATURE_DEVICE_TRACKING
|
||||||
self._port: int | None = None
|
self._port: int | None = None
|
||||||
self._username: str = ""
|
self._username: str = ""
|
||||||
self._model: str = ""
|
self._model: str = ""
|
||||||
@ -141,6 +144,7 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
options={
|
options={
|
||||||
CONF_CONSIDER_HOME: DEFAULT_CONSIDER_HOME.total_seconds(),
|
CONF_CONSIDER_HOME: DEFAULT_CONSIDER_HOME.total_seconds(),
|
||||||
CONF_OLD_DISCOVERY: DEFAULT_CONF_OLD_DISCOVERY,
|
CONF_OLD_DISCOVERY: DEFAULT_CONF_OLD_DISCOVERY,
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING: self._feature_device_discovery,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -204,6 +208,7 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
self._username = user_input[CONF_USERNAME]
|
self._username = user_input[CONF_USERNAME]
|
||||||
self._password = user_input[CONF_PASSWORD]
|
self._password = user_input[CONF_PASSWORD]
|
||||||
self._use_tls = user_input[CONF_SSL]
|
self._use_tls = user_input[CONF_SSL]
|
||||||
|
self._feature_device_discovery = user_input[CONF_FEATURE_DEVICE_TRACKING]
|
||||||
self._port = self._determine_port(user_input)
|
self._port = self._determine_port(user_input)
|
||||||
|
|
||||||
error = await self.async_fritz_tools_init()
|
error = await self.async_fritz_tools_init()
|
||||||
@ -234,6 +239,10 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
vol.Required(CONF_USERNAME): str,
|
vol.Required(CONF_USERNAME): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
vol.Optional(CONF_SSL, default=DEFAULT_SSL): bool,
|
vol.Optional(CONF_SSL, default=DEFAULT_SSL): bool,
|
||||||
|
vol.Required(
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
default=DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
): bool,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
errors=errors or {},
|
errors=errors or {},
|
||||||
@ -250,6 +259,10 @@ class FritzBoxToolsFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
vol.Required(CONF_USERNAME): str,
|
vol.Required(CONF_USERNAME): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
vol.Optional(CONF_SSL, default=DEFAULT_SSL): bool,
|
vol.Optional(CONF_SSL, default=DEFAULT_SSL): bool,
|
||||||
|
vol.Required(
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
default=DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
): bool,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
description_placeholders={"name": self._name},
|
description_placeholders={"name": self._name},
|
||||||
@ -405,7 +418,7 @@ class FritzBoxToolsOptionsFlowHandler(OptionsFlow):
|
|||||||
"""Handle options flow."""
|
"""Handle options flow."""
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
return self.async_create_entry(title="", data=user_input)
|
return self.async_create_entry(data=user_input)
|
||||||
|
|
||||||
options = self.config_entry.options
|
options = self.config_entry.options
|
||||||
data_schema = vol.Schema(
|
data_schema = vol.Schema(
|
||||||
@ -420,6 +433,13 @@ class FritzBoxToolsOptionsFlowHandler(OptionsFlow):
|
|||||||
CONF_OLD_DISCOVERY,
|
CONF_OLD_DISCOVERY,
|
||||||
default=options.get(CONF_OLD_DISCOVERY, DEFAULT_CONF_OLD_DISCOVERY),
|
default=options.get(CONF_OLD_DISCOVERY, DEFAULT_CONF_OLD_DISCOVERY),
|
||||||
): bool,
|
): bool,
|
||||||
|
vol.Optional(
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
default=options.get(
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
|
),
|
||||||
|
): bool,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return self.async_show_form(step_id="init", data_schema=data_schema)
|
return self.async_show_form(step_id="init", data_schema=data_schema)
|
||||||
|
@ -40,6 +40,9 @@ PLATFORMS = [
|
|||||||
CONF_OLD_DISCOVERY = "old_discovery"
|
CONF_OLD_DISCOVERY = "old_discovery"
|
||||||
DEFAULT_CONF_OLD_DISCOVERY = False
|
DEFAULT_CONF_OLD_DISCOVERY = False
|
||||||
|
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING = "feature_device_tracking"
|
||||||
|
DEFAULT_CONF_FEATURE_DEVICE_TRACKING = True
|
||||||
|
|
||||||
DSL_CONNECTION: Literal["dsl"] = "dsl"
|
DSL_CONNECTION: Literal["dsl"] = "dsl"
|
||||||
|
|
||||||
DEFAULT_DEVICE_NAME = "Unknown device"
|
DEFAULT_DEVICE_NAME = "Unknown device"
|
||||||
|
@ -39,6 +39,7 @@ from homeassistant.util.hass_dict import HassKey
|
|||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_OLD_DISCOVERY,
|
CONF_OLD_DISCOVERY,
|
||||||
|
DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
DEFAULT_CONF_OLD_DISCOVERY,
|
DEFAULT_CONF_OLD_DISCOVERY,
|
||||||
DEFAULT_HOST,
|
DEFAULT_HOST,
|
||||||
DEFAULT_SSL,
|
DEFAULT_SSL,
|
||||||
@ -175,6 +176,7 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
username: str = DEFAULT_USERNAME,
|
username: str = DEFAULT_USERNAME,
|
||||||
host: str = DEFAULT_HOST,
|
host: str = DEFAULT_HOST,
|
||||||
use_tls: bool = DEFAULT_SSL,
|
use_tls: bool = DEFAULT_SSL,
|
||||||
|
device_discovery_enabled: bool = DEFAULT_CONF_FEATURE_DEVICE_TRACKING,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize FritzboxTools class."""
|
"""Initialize FritzboxTools class."""
|
||||||
super().__init__(
|
super().__init__(
|
||||||
@ -202,6 +204,7 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
self.port = port
|
self.port = port
|
||||||
self.username = username
|
self.username = username
|
||||||
self.use_tls = use_tls
|
self.use_tls = use_tls
|
||||||
|
self.device_discovery_enabled = device_discovery_enabled
|
||||||
self.has_call_deflections: bool = False
|
self.has_call_deflections: bool = False
|
||||||
self._model: str | None = None
|
self._model: str | None = None
|
||||||
self._current_firmware: str | None = None
|
self._current_firmware: str | None = None
|
||||||
@ -332,10 +335,15 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
"entity_states": {},
|
"entity_states": {},
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
|
await self.async_update_device_info()
|
||||||
|
|
||||||
|
if self.device_discovery_enabled:
|
||||||
await self.async_scan_devices()
|
await self.async_scan_devices()
|
||||||
|
|
||||||
entity_data["entity_states"] = await self.hass.async_add_executor_job(
|
entity_data["entity_states"] = await self.hass.async_add_executor_job(
|
||||||
self._entity_states_update
|
self._entity_states_update
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.has_call_deflections:
|
if self.has_call_deflections:
|
||||||
entity_data[
|
entity_data[
|
||||||
"call_deflections"
|
"call_deflections"
|
||||||
@ -551,12 +559,8 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
if new_device:
|
if new_device:
|
||||||
async_dispatcher_send(self.hass, self.signal_device_new)
|
async_dispatcher_send(self.hass, self.signal_device_new)
|
||||||
|
|
||||||
async def async_scan_devices(self, now: datetime | None = None) -> None:
|
async def async_update_device_info(self, now: datetime | None = None) -> None:
|
||||||
"""Scan for new devices and return a list of found device ids."""
|
"""Update own device information."""
|
||||||
|
|
||||||
if self.hass.is_stopping:
|
|
||||||
_ha_is_stopping("scan devices")
|
|
||||||
return
|
|
||||||
|
|
||||||
_LOGGER.debug("Checking host info for FRITZ!Box device %s", self.host)
|
_LOGGER.debug("Checking host info for FRITZ!Box device %s", self.host)
|
||||||
(
|
(
|
||||||
@ -565,6 +569,13 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
self._release_url,
|
self._release_url,
|
||||||
) = await self._async_update_device_info()
|
) = await self._async_update_device_info()
|
||||||
|
|
||||||
|
async def async_scan_devices(self, now: datetime | None = None) -> None:
|
||||||
|
"""Scan for new network devices."""
|
||||||
|
|
||||||
|
if self.hass.is_stopping:
|
||||||
|
_ha_is_stopping("scan devices")
|
||||||
|
return
|
||||||
|
|
||||||
_LOGGER.debug("Checking devices for FRITZ!Box device %s", self.host)
|
_LOGGER.debug("Checking devices for FRITZ!Box device %s", self.host)
|
||||||
_default_consider_home = DEFAULT_CONSIDER_HOME.total_seconds()
|
_default_consider_home = DEFAULT_CONSIDER_HOME.total_seconds()
|
||||||
if self._options:
|
if self._options:
|
||||||
@ -683,6 +694,9 @@ class FritzBoxTools(DataUpdateCoordinator[UpdateCoordinatorDataType]):
|
|||||||
|
|
||||||
async def async_trigger_cleanup(self) -> None:
|
async def async_trigger_cleanup(self) -> None:
|
||||||
"""Trigger device trackers cleanup."""
|
"""Trigger device trackers cleanup."""
|
||||||
|
_LOGGER.debug("Device tracker cleanup triggered")
|
||||||
|
device_hosts = {self.mac: Device(True, "", "", "", "", None)}
|
||||||
|
if self.device_discovery_enabled:
|
||||||
device_hosts = await self._async_update_hosts_info()
|
device_hosts = await self._async_update_hosts_info()
|
||||||
entity_reg: er.EntityRegistry = er.async_get(self.hass)
|
entity_reg: er.EntityRegistry = er.async_get(self.hass)
|
||||||
config_entry = self.config_entry
|
config_entry = self.config_entry
|
||||||
|
@ -4,7 +4,9 @@
|
|||||||
"data_description_port": "Leave empty to use the default port.",
|
"data_description_port": "Leave empty to use the default port.",
|
||||||
"data_description_username": "Username for the FRITZ!Box.",
|
"data_description_username": "Username for the FRITZ!Box.",
|
||||||
"data_description_password": "Password for the FRITZ!Box.",
|
"data_description_password": "Password for the FRITZ!Box.",
|
||||||
"data_description_ssl": "Use SSL to connect to the FRITZ!Box."
|
"data_description_ssl": "Use SSL to connect to the FRITZ!Box.",
|
||||||
|
"data_description_feature_device_tracking": "Enable or disable the network device tracking feature.",
|
||||||
|
"data_feature_device_tracking": "Enable network device tracking"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"flow_title": "{name}",
|
"flow_title": "{name}",
|
||||||
@ -15,12 +17,14 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"username": "[%key:common::config_flow::data::username%]",
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
"password": "[%key:common::config_flow::data::password%]",
|
"password": "[%key:common::config_flow::data::password%]",
|
||||||
"ssl": "[%key:common::config_flow::data::ssl%]"
|
"ssl": "[%key:common::config_flow::data::ssl%]",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_feature_device_tracking%]"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"username": "[%key:component::fritz::common::data_description_username%]",
|
"username": "[%key:component::fritz::common::data_description_username%]",
|
||||||
"password": "[%key:component::fritz::common::data_description_password%]",
|
"password": "[%key:component::fritz::common::data_description_password%]",
|
||||||
"ssl": "[%key:component::fritz::common::data_description_ssl%]"
|
"ssl": "[%key:component::fritz::common::data_description_ssl%]",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_description_feature_device_tracking%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reauth_confirm": {
|
"reauth_confirm": {
|
||||||
@ -57,14 +61,16 @@
|
|||||||
"port": "[%key:common::config_flow::data::port%]",
|
"port": "[%key:common::config_flow::data::port%]",
|
||||||
"username": "[%key:common::config_flow::data::username%]",
|
"username": "[%key:common::config_flow::data::username%]",
|
||||||
"password": "[%key:common::config_flow::data::password%]",
|
"password": "[%key:common::config_flow::data::password%]",
|
||||||
"ssl": "[%key:common::config_flow::data::ssl%]"
|
"ssl": "[%key:common::config_flow::data::ssl%]",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_feature_device_tracking%]"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"host": "[%key:component::fritz::common::data_description_host%]",
|
"host": "[%key:component::fritz::common::data_description_host%]",
|
||||||
"port": "[%key:component::fritz::common::data_description_port%]",
|
"port": "[%key:component::fritz::common::data_description_port%]",
|
||||||
"username": "[%key:component::fritz::common::data_description_username%]",
|
"username": "[%key:component::fritz::common::data_description_username%]",
|
||||||
"password": "[%key:component::fritz::common::data_description_password%]",
|
"password": "[%key:component::fritz::common::data_description_password%]",
|
||||||
"ssl": "[%key:component::fritz::common::data_description_ssl%]"
|
"ssl": "[%key:component::fritz::common::data_description_ssl%]",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_description_feature_device_tracking%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -89,11 +95,13 @@
|
|||||||
"init": {
|
"init": {
|
||||||
"data": {
|
"data": {
|
||||||
"consider_home": "Seconds to consider a device at 'home'",
|
"consider_home": "Seconds to consider a device at 'home'",
|
||||||
"old_discovery": "Enable old discovery method"
|
"old_discovery": "Enable old discovery method",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_feature_device_tracking%]"
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"consider_home": "Time in seconds to consider a device at home. Default is 180 seconds.",
|
"consider_home": "Time in seconds to consider a device at home. Default is 180 seconds.",
|
||||||
"old_discovery": "Enable old discovery method. This is needed for some scenarios."
|
"old_discovery": "Enable old discovery method. This is needed for some scenarios.",
|
||||||
|
"feature_device_tracking": "[%key:component::fritz::common::data_description_feature_device_tracking%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ from homeassistant.components.device_tracker import (
|
|||||||
DEFAULT_CONSIDER_HOME,
|
DEFAULT_CONSIDER_HOME,
|
||||||
)
|
)
|
||||||
from homeassistant.components.fritz.const import (
|
from homeassistant.components.fritz.const import (
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING,
|
||||||
CONF_OLD_DISCOVERY,
|
CONF_OLD_DISCOVERY,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
ERROR_AUTH_INVALID,
|
ERROR_AUTH_INVALID,
|
||||||
@ -744,6 +745,7 @@ async def test_options_flow(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
CONF_OLD_DISCOVERY: False,
|
CONF_OLD_DISCOVERY: False,
|
||||||
CONF_CONSIDER_HOME: 37,
|
CONF_CONSIDER_HOME: 37,
|
||||||
|
CONF_FEATURE_DEVICE_TRACKING: True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user