core/homeassistant/components/freedns/__init__.py

104 lines
2.9 KiB
Python

"""Integrate with FreeDNS Dynamic DNS service at freedns.afraid.org."""
import asyncio
from datetime import datetime, timedelta
import logging
import aiohttp
import voluptuous as vol
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_SCAN_INTERVAL, CONF_URL
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__)
DOMAIN = "freedns"
DEFAULT_INTERVAL = timedelta(minutes=10)
TIMEOUT = 10
UPDATE_URL = "https://freedns.afraid.org/dynamic/update.php"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Exclusive(CONF_URL, DOMAIN): cv.string,
vol.Exclusive(CONF_ACCESS_TOKEN, DOMAIN): cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_INTERVAL): vol.All(
cv.time_period, cv.positive_timedelta
),
}
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Initialize the FreeDNS component."""
conf = config[DOMAIN]
url = conf.get(CONF_URL)
auth_token = conf.get(CONF_ACCESS_TOKEN)
update_interval = conf[CONF_SCAN_INTERVAL]
session = async_get_clientsession(hass)
result = await _update_freedns(hass, session, url, auth_token)
if result is False:
return False
async def update_domain_callback(now: datetime) -> None:
"""Update the FreeDNS entry."""
await _update_freedns(hass, session, url, auth_token)
async_track_time_interval(
hass, update_domain_callback, update_interval, cancel_on_shutdown=True
)
return True
async def _update_freedns(hass, session, url, auth_token):
"""Update FreeDNS."""
params = None
if url is None:
url = UPDATE_URL
if auth_token is not None:
params = {}
params[auth_token] = ""
try:
async with asyncio.timeout(TIMEOUT):
resp = await session.get(url, params=params)
body = await resp.text()
if "has not changed" in body:
# IP has not changed.
_LOGGER.debug("FreeDNS update skipped: IP has not changed")
return True
if "ERROR" not in body:
_LOGGER.debug("Updating FreeDNS was successful: %s", body)
return True
if "Invalid update URL" in body:
_LOGGER.error("FreeDNS update token is invalid")
else:
_LOGGER.warning("Updating FreeDNS failed: %s", body)
except aiohttp.ClientError:
_LOGGER.warning("Can't connect to FreeDNS API")
except TimeoutError:
_LOGGER.warning("Timeout from FreeDNS API at %s", url)
return False