82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
"""The Open Thread Border Router integration."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Callable, Coroutine
|
|
import dataclasses
|
|
from functools import wraps
|
|
from typing import Any, Concatenate, ParamSpec, TypeVar
|
|
|
|
import python_otbr_api
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
from homeassistant.helpers.typing import ConfigType
|
|
|
|
from . import websocket_api
|
|
from .const import DOMAIN
|
|
|
|
_R = TypeVar("_R")
|
|
_P = ParamSpec("_P")
|
|
|
|
|
|
def _handle_otbr_error(
|
|
func: Callable[Concatenate[OTBRData, _P], Coroutine[Any, Any, _R]]
|
|
) -> Callable[Concatenate[OTBRData, _P], Coroutine[Any, Any, _R]]:
|
|
"""Handle OTBR errors."""
|
|
|
|
@wraps(func)
|
|
async def _func(self: OTBRData, *args: _P.args, **kwargs: _P.kwargs) -> _R:
|
|
try:
|
|
return await func(self, *args, **kwargs)
|
|
except python_otbr_api.OTBRError as exc:
|
|
raise HomeAssistantError("Failed to call OTBR API") from exc
|
|
|
|
return _func
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class OTBRData:
|
|
"""Container for OTBR data."""
|
|
|
|
url: str
|
|
api: python_otbr_api.OTBR
|
|
|
|
@_handle_otbr_error
|
|
async def get_active_dataset_tlvs(self) -> bytes | None:
|
|
"""Get current active operational dataset in TLVS format, or None."""
|
|
return await self.api.get_active_dataset_tlvs()
|
|
|
|
|
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
"""Set up the Open Thread Border Router component."""
|
|
websocket_api.async_setup(hass)
|
|
return True
|
|
|
|
|
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Set up an Open Thread Border Router config entry."""
|
|
api = python_otbr_api.OTBR(entry.data["url"], async_get_clientsession(hass), 10)
|
|
hass.data[DOMAIN] = OTBRData(entry.data["url"], api)
|
|
return True
|
|
|
|
|
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Unload a config entry."""
|
|
hass.data.pop(DOMAIN)
|
|
return True
|
|
|
|
|
|
async def async_get_active_dataset_tlvs(hass: HomeAssistant) -> bytes | None:
|
|
"""Get current active operational dataset in TLVS format, or None.
|
|
|
|
Returns None if there is no active operational dataset.
|
|
Raises if the http status is 400 or higher or if the response is invalid.
|
|
"""
|
|
if DOMAIN not in hass.data:
|
|
raise HomeAssistantError("OTBR API not available")
|
|
|
|
data: OTBRData = hass.data[DOMAIN]
|
|
return await data.get_active_dataset_tlvs()
|