forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor Freebox : add config flow + temperature sensor + signal disp…
…atch (home-assistant#30334) * Add config flow to Freebox * Add manufacturer in device_tracker info * Add device_info to sensor + switch * Add device_info: connections * Add config_flow test + update .coveragerc * Typing * Add device_type icon * Remove one error log * Fix pylint * Add myself as CODEOWNER * Handle sync in one place * Separate the Freebox[Router/Device/Sensor] from __init__.py * Add link step to config flow * Make temperature sensors auto-discovered * Use device activity instead of reachablility for device_tracker * Store token file in .storage Depending on host if list of Freebox integration on the future without breaking change * Remove IP sensors + add Freebox router as a device with attrs : IPs, conection type, uptime, version & serial * Add sensor should_poll=False * Test typing * Handle devices with no name * None is the default for data * Fix comment * Use config_entry.unique_id * Add async_unload_entry with asyncio * Add and use bunch of data size and rate related constants (home-assistant#31781) * Review * Remove useless "already_configured" error string * Review : merge 2 device & 2 sensor classes * Entities from platforms * Fix unload + add device after setup + clean loggers * async_add_entities True * Review * Use pathlib + refactor get_api * device_tracker set + tests with CoroutineMock() * Removing active & reachable from tracker attrs * Review * Fix pipeline * typing * typing * typing * Raise ConfigEntryNotReady when HttpRequestError at setup * Review * Multiple Freebox s * Review: store sensors in router * Freebox: a sensor story
- Loading branch information
Showing
17 changed files
with
922 additions
and
170 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"config": { | ||
"abort": { | ||
"already_configured": "Host already configured" | ||
}, | ||
"error": { | ||
"connection_failed": "Failed to connect, please try again", | ||
"register_failed": "Failed to register, please try again", | ||
"unknown": "Unknown error: please retry later" | ||
}, | ||
"step": { | ||
"link": { | ||
"description": "Click \"Submit\", then touch the right arrow on the router to register Freebox with Home Assistant.\n\n![Location of button on the router](/static/images/config_freebox.png)", | ||
"title": "Link Freebox router" | ||
}, | ||
"user": { | ||
"data": { | ||
"host": "Host", | ||
"port": "Port" | ||
}, | ||
"title": "Freebox" | ||
} | ||
}, | ||
"title": "Freebox" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
"""Config flow to configure the Freebox integration.""" | ||
import logging | ||
|
||
from aiofreepybox.exceptions import AuthorizationError, HttpRequestError | ||
import voluptuous as vol | ||
|
||
from homeassistant import config_entries | ||
from homeassistant.const import CONF_HOST, CONF_PORT | ||
|
||
from .const import DOMAIN # pylint: disable=unused-import | ||
from .router import get_api | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
class FreeboxFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): | ||
"""Handle a config flow.""" | ||
|
||
VERSION = 1 | ||
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL | ||
|
||
def __init__(self): | ||
"""Initialize Freebox config flow.""" | ||
self._host = None | ||
self._port = None | ||
|
||
def _show_setup_form(self, user_input=None, errors=None): | ||
"""Show the setup form to the user.""" | ||
|
||
if user_input is None: | ||
user_input = {} | ||
|
||
return self.async_show_form( | ||
step_id="user", | ||
data_schema=vol.Schema( | ||
{ | ||
vol.Required(CONF_HOST, default=user_input.get(CONF_HOST, "")): str, | ||
vol.Required(CONF_PORT, default=user_input.get(CONF_PORT, "")): int, | ||
} | ||
), | ||
errors=errors or {}, | ||
) | ||
|
||
async def async_step_user(self, user_input=None): | ||
"""Handle a flow initiated by the user.""" | ||
errors = {} | ||
|
||
if user_input is None: | ||
return self._show_setup_form(user_input, errors) | ||
|
||
self._host = user_input[CONF_HOST] | ||
self._port = user_input[CONF_PORT] | ||
|
||
# Check if already configured | ||
await self.async_set_unique_id(self._host) | ||
self._abort_if_unique_id_configured() | ||
|
||
return await self.async_step_link() | ||
|
||
async def async_step_link(self, user_input=None): | ||
"""Attempt to link with the Freebox router. | ||
Given a configured host, will ask the user to press the button | ||
to connect to the router. | ||
""" | ||
if user_input is None: | ||
return self.async_show_form(step_id="link") | ||
|
||
errors = {} | ||
|
||
fbx = await get_api(self.hass, self._host) | ||
try: | ||
# Open connection and check authentication | ||
await fbx.open(self._host, self._port) | ||
|
||
# Check permissions | ||
await fbx.system.get_config() | ||
await fbx.lan.get_hosts_list() | ||
await self.hass.async_block_till_done() | ||
|
||
# Close connection | ||
await fbx.close() | ||
|
||
return self.async_create_entry( | ||
title=self._host, data={CONF_HOST: self._host, CONF_PORT: self._port}, | ||
) | ||
|
||
except AuthorizationError as error: | ||
_LOGGER.error(error) | ||
errors["base"] = "register_failed" | ||
|
||
except HttpRequestError: | ||
_LOGGER.error("Error connecting to the Freebox router at %s", self._host) | ||
errors["base"] = "connection_failed" | ||
|
||
except Exception: # pylint: disable=broad-except | ||
_LOGGER.exception( | ||
"Unknown error connecting with Freebox router at %s", self._host | ||
) | ||
errors["base"] = "unknown" | ||
|
||
return self.async_show_form(step_id="link", errors=errors) | ||
|
||
async def async_step_import(self, user_input=None): | ||
"""Import a config entry.""" | ||
return await self.async_step_user(user_input) | ||
|
||
async def async_step_discovery(self, user_input=None): | ||
"""Initialize step from discovery.""" | ||
return await self.async_step_user(user_input) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
"""Freebox component constants.""" | ||
import socket | ||
|
||
from homeassistant.const import ( | ||
DATA_RATE_KILOBYTES_PER_SECOND, | ||
DEVICE_CLASS_TEMPERATURE, | ||
TEMP_CELSIUS, | ||
) | ||
|
||
DOMAIN = "freebox" | ||
|
||
APP_DESC = { | ||
"app_id": "hass", | ||
"app_name": "Home Assistant", | ||
"app_version": "0.106", | ||
"device_name": socket.gethostname(), | ||
} | ||
API_VERSION = "v6" | ||
|
||
PLATFORMS = ["device_tracker", "sensor", "switch"] | ||
|
||
DEFAULT_DEVICE_NAME = "Unknown device" | ||
|
||
# to store the cookie | ||
STORAGE_KEY = DOMAIN | ||
STORAGE_VERSION = 1 | ||
|
||
# Sensor | ||
SENSOR_NAME = "name" | ||
SENSOR_UNIT = "unit" | ||
SENSOR_ICON = "icon" | ||
SENSOR_DEVICE_CLASS = "device_class" | ||
|
||
CONNECTION_SENSORS = { | ||
"rate_down": { | ||
SENSOR_NAME: "Freebox download speed", | ||
SENSOR_UNIT: DATA_RATE_KILOBYTES_PER_SECOND, | ||
SENSOR_ICON: "mdi:download-network", | ||
SENSOR_DEVICE_CLASS: None, | ||
}, | ||
"rate_up": { | ||
SENSOR_NAME: "Freebox upload speed", | ||
SENSOR_UNIT: DATA_RATE_KILOBYTES_PER_SECOND, | ||
SENSOR_ICON: "mdi:upload-network", | ||
SENSOR_DEVICE_CLASS: None, | ||
}, | ||
} | ||
|
||
TEMPERATURE_SENSOR_TEMPLATE = { | ||
SENSOR_NAME: None, | ||
SENSOR_UNIT: TEMP_CELSIUS, | ||
SENSOR_ICON: "mdi:thermometer", | ||
SENSOR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, | ||
} | ||
|
||
# Icons | ||
DEVICE_ICONS = { | ||
"freebox_delta": "mdi:television-guide", | ||
"freebox_hd": "mdi:television-guide", | ||
"freebox_mini": "mdi:television-guide", | ||
"freebox_player": "mdi:television-guide", | ||
"ip_camera": "mdi:cctv", | ||
"ip_phone": "mdi:phone-voip", | ||
"laptop": "mdi:laptop", | ||
"multimedia_device": "mdi:play-network", | ||
"nas": "mdi:nas", | ||
"networking_device": "mdi:network", | ||
"printer": "mdi:printer", | ||
"router": "mdi:router-wireless", | ||
"smartphone": "mdi:cellphone", | ||
"tablet": "mdi:tablet", | ||
"television": "mdi:television", | ||
"vg_console": "mdi:gamepad-variant", | ||
"workstation": "mdi:desktop-tower-monitor", | ||
} |
Oops, something went wrong.