mirror of
https://github.com/home-assistant/core.git
synced 2026-07-01 11:46:40 +01:00
200 lines
5.8 KiB
Python
200 lines
5.8 KiB
Python
"""Support for the Transmission BitTorrent client API."""
|
|
|
|
from functools import partial
|
|
import logging
|
|
import re
|
|
from typing import Any, Final
|
|
|
|
import transmission_rpc
|
|
from transmission_rpc.error import (
|
|
TransmissionAuthError,
|
|
TransmissionConnectError,
|
|
TransmissionError,
|
|
)
|
|
|
|
from homeassistant.const import (
|
|
CONF_HOST,
|
|
CONF_NAME,
|
|
CONF_PASSWORD,
|
|
CONF_PATH,
|
|
CONF_PORT,
|
|
CONF_SSL,
|
|
CONF_USERNAME,
|
|
Platform,
|
|
)
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.exceptions import (
|
|
ConfigEntryAuthFailed,
|
|
ConfigEntryError,
|
|
ConfigEntryNotReady,
|
|
)
|
|
from homeassistant.helpers import (
|
|
config_validation as cv,
|
|
device_registry as dr,
|
|
entity_registry as er,
|
|
)
|
|
from homeassistant.helpers.device_registry import DeviceEntryType
|
|
from homeassistant.helpers.typing import ConfigType
|
|
|
|
from .const import DEFAULT_PATH, DEFAULT_SSL, DOMAIN, MIN_REQUIRED_TRANSMISSION_VERSION
|
|
from .coordinator import TransmissionConfigEntry, TransmissionDataUpdateCoordinator
|
|
from .helpers import create_version
|
|
from .services import async_setup_services
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
PLATFORMS = [Platform.EVENT, Platform.SENSOR, Platform.SWITCH]
|
|
|
|
MIGRATION_NAME_TO_KEY = {
|
|
# Sensors
|
|
"Down Speed": "download",
|
|
"Up Speed": "upload",
|
|
"Status": "status",
|
|
"Active Torrents": "active_torrents",
|
|
"Paused Torrents": "paused_torrents",
|
|
"Total Torrents": "total_torrents",
|
|
"Completed Torrents": "completed_torrents",
|
|
"Started Torrents": "started_torrents",
|
|
# Switches
|
|
"Switch": "on_off",
|
|
"Turtle Mode": "turtle_mode",
|
|
}
|
|
|
|
|
|
CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
|
|
|
|
|
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
"""Set up the Transmission component."""
|
|
async_setup_services(hass)
|
|
return True
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant, config_entry: TransmissionConfigEntry
|
|
) -> bool:
|
|
"""Set up the Transmission Component."""
|
|
|
|
@callback
|
|
def update_unique_id(
|
|
entity_entry: er.RegistryEntry,
|
|
) -> dict[str, Any] | None:
|
|
"""Update unique ID of entity entry."""
|
|
if CONF_NAME not in config_entry.data:
|
|
return None
|
|
match = re.search(
|
|
f"{config_entry.data[CONF_HOST]}"
|
|
f"-{config_entry.data[CONF_NAME]} (?P<name>.+)",
|
|
entity_entry.unique_id,
|
|
)
|
|
|
|
if match and (key := MIGRATION_NAME_TO_KEY.get(match.group("name"))):
|
|
return {"new_unique_id": f"{config_entry.entry_id}-{key}"}
|
|
return None
|
|
|
|
await er.async_migrate_entries(hass, config_entry.entry_id, update_unique_id)
|
|
|
|
try:
|
|
api = await get_api(hass, dict(config_entry.data))
|
|
except TransmissionAuthError as err:
|
|
raise ConfigEntryAuthFailed from err
|
|
except (TransmissionConnectError, TransmissionError) as err:
|
|
raise ConfigEntryNotReady from err
|
|
|
|
version = create_version(api.server_version)
|
|
if version.valid and version < MIN_REQUIRED_TRANSMISSION_VERSION:
|
|
raise ConfigEntryError(
|
|
translation_domain=DOMAIN,
|
|
translation_key="version_error",
|
|
translation_placeholders={
|
|
"transmission_version": api.server_version,
|
|
"min_version": MIN_REQUIRED_TRANSMISSION_VERSION,
|
|
},
|
|
)
|
|
|
|
protocol: Final = "https" if config_entry.data[CONF_SSL] else "http"
|
|
device_registry = dr.async_get(hass)
|
|
device_registry.async_get_or_create(
|
|
config_entry_id=config_entry.entry_id,
|
|
identifiers={(DOMAIN, config_entry.entry_id)},
|
|
manufacturer="Transmission",
|
|
entry_type=DeviceEntryType.SERVICE,
|
|
sw_version=api.server_version,
|
|
configuration_url=(
|
|
f"{protocol}://{config_entry.data[CONF_HOST]}:{config_entry.data[CONF_PORT]}"
|
|
),
|
|
)
|
|
|
|
coordinator = TransmissionDataUpdateCoordinator(hass, config_entry, api)
|
|
await hass.async_add_executor_job(coordinator.init_torrent_list)
|
|
|
|
await coordinator.async_config_entry_first_refresh()
|
|
config_entry.runtime_data = coordinator
|
|
|
|
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
|
|
|
return True
|
|
|
|
|
|
async def async_unload_entry(
|
|
hass: HomeAssistant, config_entry: TransmissionConfigEntry
|
|
) -> bool:
|
|
"""Unload Transmission Entry from config_entry."""
|
|
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)
|
|
|
|
|
|
async def async_migrate_entry(
|
|
hass: HomeAssistant, config_entry: TransmissionConfigEntry
|
|
) -> bool:
|
|
"""Migrate an old config entry."""
|
|
_LOGGER.debug(
|
|
"Migrating from version %s.%s",
|
|
config_entry.version,
|
|
config_entry.minor_version,
|
|
)
|
|
|
|
if config_entry.version == 1:
|
|
if config_entry.minor_version < 2:
|
|
new = {**config_entry.data}
|
|
new[CONF_PATH] = DEFAULT_PATH
|
|
new[CONF_SSL] = DEFAULT_SSL
|
|
|
|
hass.config_entries.async_update_entry(
|
|
config_entry, data=new, version=1, minor_version=2
|
|
)
|
|
|
|
_LOGGER.debug(
|
|
"Migration to version %s.%s successful",
|
|
config_entry.version,
|
|
config_entry.minor_version,
|
|
)
|
|
|
|
return True
|
|
|
|
|
|
async def get_api(
|
|
hass: HomeAssistant, entry: dict[str, Any]
|
|
) -> transmission_rpc.Client:
|
|
"""Get Transmission client."""
|
|
protocol: Final = "https" if entry[CONF_SSL] else "http"
|
|
host = entry[CONF_HOST]
|
|
port = entry[CONF_PORT]
|
|
path = entry[CONF_PATH]
|
|
username = entry.get(CONF_USERNAME)
|
|
password = entry.get(CONF_PASSWORD)
|
|
|
|
api = await hass.async_add_executor_job(
|
|
partial(
|
|
transmission_rpc.Client,
|
|
username=username,
|
|
password=password,
|
|
protocol=protocol,
|
|
host=host,
|
|
port=port,
|
|
path=path,
|
|
)
|
|
)
|
|
|
|
_LOGGER.debug("Successfully connected to %s", host)
|
|
return api
|