mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add Freebox device tracker (#12727)
* Add a device tracker for Freebox routers * Automatic setup of Freebox device tracker based on discovery * Make the Freebox device tracker asynchronous
This commit is contained in:
parent
549abd9c7e
commit
103639455c
@ -397,6 +397,7 @@ omit =
|
|||||||
homeassistant/components/device_tracker/bt_home_hub_5.py
|
homeassistant/components/device_tracker/bt_home_hub_5.py
|
||||||
homeassistant/components/device_tracker/cisco_ios.py
|
homeassistant/components/device_tracker/cisco_ios.py
|
||||||
homeassistant/components/device_tracker/ddwrt.py
|
homeassistant/components/device_tracker/ddwrt.py
|
||||||
|
homeassistant/components/device_tracker/freebox.py
|
||||||
homeassistant/components/device_tracker/fritz.py
|
homeassistant/components/device_tracker/fritz.py
|
||||||
homeassistant/components/device_tracker/google_maps.py
|
homeassistant/components/device_tracker/google_maps.py
|
||||||
homeassistant/components/device_tracker/gpslogger.py
|
homeassistant/components/device_tracker/gpslogger.py
|
||||||
|
120
homeassistant/components/device_tracker/freebox.py
Normal file
120
homeassistant/components/device_tracker/freebox.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
"""
|
||||||
|
Support for device tracking through Freebox routers.
|
||||||
|
|
||||||
|
This tracker keeps track of the devices connected to the configured Freebox.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/device_tracker.freebox/
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
import copy
|
||||||
|
import logging
|
||||||
|
import socket
|
||||||
|
from collections import namedtuple
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
|
from homeassistant.components.device_tracker import (
|
||||||
|
PLATFORM_SCHEMA, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||||
|
from homeassistant.const import (
|
||||||
|
CONF_HOST, CONF_PORT)
|
||||||
|
|
||||||
|
REQUIREMENTS = ['aiofreepybox==0.0.3']
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
FREEBOX_CONFIG_FILE = 'freebox.conf'
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.All(
|
||||||
|
PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Required(CONF_HOST): cv.string,
|
||||||
|
vol.Required(CONF_PORT): cv.port
|
||||||
|
}))
|
||||||
|
|
||||||
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_scanner(hass, config, async_see, discovery_info=None):
|
||||||
|
"""Set up the Freebox device tracker and start the polling."""
|
||||||
|
freebox_config = copy.deepcopy(config)
|
||||||
|
if discovery_info is not None:
|
||||||
|
freebox_config[CONF_HOST] = discovery_info['properties']['api_domain']
|
||||||
|
freebox_config[CONF_PORT] = discovery_info['properties']['https_port']
|
||||||
|
_LOGGER.info("Discovered Freebox server: %s:%s",
|
||||||
|
freebox_config[CONF_HOST], freebox_config[CONF_PORT])
|
||||||
|
|
||||||
|
scanner = FreeboxDeviceScanner(hass, freebox_config, async_see)
|
||||||
|
interval = freebox_config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||||
|
await scanner.async_start(hass, interval)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
Device = namedtuple('Device', ['id', 'name', 'ip'])
|
||||||
|
|
||||||
|
|
||||||
|
def _build_device(device_dict):
|
||||||
|
return Device(
|
||||||
|
device_dict['l2ident']['id'],
|
||||||
|
device_dict['primary_name'],
|
||||||
|
device_dict['l3connectivities'][0]['addr'])
|
||||||
|
|
||||||
|
|
||||||
|
class FreeboxDeviceScanner(object):
|
||||||
|
"""This class scans for devices connected to the Freebox."""
|
||||||
|
|
||||||
|
def __init__(self, hass, config, async_see):
|
||||||
|
"""Initialize the scanner."""
|
||||||
|
from aiofreepybox import Freepybox
|
||||||
|
|
||||||
|
self.host = config[CONF_HOST]
|
||||||
|
self.port = config[CONF_PORT]
|
||||||
|
self.token_file = hass.config.path(FREEBOX_CONFIG_FILE)
|
||||||
|
self.async_see = async_see
|
||||||
|
|
||||||
|
# Hardcode the app description to avoid invalidating the authentication
|
||||||
|
# file at each new version.
|
||||||
|
# The version can be changed if we want the user to re-authorize HASS
|
||||||
|
# on her Freebox.
|
||||||
|
app_desc = {
|
||||||
|
'app_id': 'hass',
|
||||||
|
'app_name': 'Home Assistant',
|
||||||
|
'app_version': '0.65',
|
||||||
|
'device_name': socket.gethostname()
|
||||||
|
}
|
||||||
|
|
||||||
|
api_version = 'v1' # Use the lowest working version.
|
||||||
|
self.fbx = Freepybox(
|
||||||
|
app_desc=app_desc,
|
||||||
|
token_file=self.token_file,
|
||||||
|
api_version=api_version)
|
||||||
|
|
||||||
|
async def async_start(self, hass, interval):
|
||||||
|
"""Perform a first update and start polling at the given interval."""
|
||||||
|
await self.async_update_info()
|
||||||
|
interval = max(interval, MIN_TIME_BETWEEN_SCANS)
|
||||||
|
async_track_time_interval(hass, self.async_update_info, interval)
|
||||||
|
|
||||||
|
async def async_update_info(self, now=None):
|
||||||
|
"""Check the Freebox for devices."""
|
||||||
|
from aiofreepybox.exceptions import HttpRequestError
|
||||||
|
|
||||||
|
_LOGGER.info('Scanning devices')
|
||||||
|
|
||||||
|
await self.fbx.open(self.host, self.port)
|
||||||
|
try:
|
||||||
|
hosts = await self.fbx.lan.get_hosts_list()
|
||||||
|
except HttpRequestError:
|
||||||
|
_LOGGER.exception('Failed to scan devices')
|
||||||
|
else:
|
||||||
|
active_devices = [_build_device(device)
|
||||||
|
for device in hosts
|
||||||
|
if device['active']]
|
||||||
|
|
||||||
|
if active_devices:
|
||||||
|
await asyncio.wait([self.async_see(mac=d.id, host_name=d.name)
|
||||||
|
for d in active_devices])
|
||||||
|
|
||||||
|
await self.fbx.close()
|
@ -84,6 +84,7 @@ SERVICE_HANDLERS = {
|
|||||||
'kodi': ('media_player', 'kodi'),
|
'kodi': ('media_player', 'kodi'),
|
||||||
'volumio': ('media_player', 'volumio'),
|
'volumio': ('media_player', 'volumio'),
|
||||||
'nanoleaf_aurora': ('light', 'nanoleaf_aurora'),
|
'nanoleaf_aurora': ('light', 'nanoleaf_aurora'),
|
||||||
|
'freebox': ('device_tracker', 'freebox'),
|
||||||
}
|
}
|
||||||
|
|
||||||
OPTIONAL_SERVICE_HANDLERS = {
|
OPTIONAL_SERVICE_HANDLERS = {
|
||||||
|
@ -81,6 +81,9 @@ aioautomatic==0.6.5
|
|||||||
# homeassistant.components.sensor.dnsip
|
# homeassistant.components.sensor.dnsip
|
||||||
aiodns==1.1.1
|
aiodns==1.1.1
|
||||||
|
|
||||||
|
# homeassistant.components.device_tracker.freebox
|
||||||
|
aiofreepybox==0.0.3
|
||||||
|
|
||||||
# homeassistant.components.emulated_hue
|
# homeassistant.components.emulated_hue
|
||||||
# homeassistant.components.http
|
# homeassistant.components.http
|
||||||
aiohttp_cors==0.7.0
|
aiohttp_cors==0.7.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user