76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
"""State shared by all ninlight entries: the firmware catalog and one-time download keys."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|
from homeassistant.helpers.event import async_track_time_interval
|
|
from homeassistant.util.hass_dict import HassKey
|
|
|
|
from .const import CATALOG_SCAN_INTERVAL, DOMAIN, FIRMWARE_DIR_NAME, SIGNAL_CATALOG_UPDATED
|
|
from .firmware import FirmwareCatalog
|
|
from .http import NinlightFirmwareView, OtaRegistry
|
|
|
|
|
|
def firmware_directory(hass: HomeAssistant) -> Path:
|
|
return Path(hass.config.path(FIRMWARE_DIR_NAME))
|
|
|
|
|
|
@dataclass
|
|
class NinlightShared:
|
|
"""One instance per Home Assistant."""
|
|
|
|
catalog: FirmwareCatalog
|
|
registry: OtaRegistry
|
|
scan_lock: asyncio.Lock = field(default_factory=asyncio.Lock)
|
|
unsub_scan: CALLBACK_TYPE | None = None
|
|
|
|
|
|
DATA_SHARED: HassKey[NinlightShared] = HassKey(DOMAIN)
|
|
|
|
|
|
@callback
|
|
def async_get_shared(hass: HomeAssistant) -> NinlightShared:
|
|
"""Create on first use and register the download view exactly once."""
|
|
shared = hass.data.get(DATA_SHARED)
|
|
if shared is None:
|
|
shared = NinlightShared(FirmwareCatalog(firmware_directory(hass)), OtaRegistry())
|
|
hass.data[DATA_SHARED] = shared
|
|
hass.http.register_view(NinlightFirmwareView(hass, shared.registry))
|
|
return shared
|
|
|
|
|
|
async def async_scan_catalog(hass: HomeAssistant, shared: NinlightShared) -> None:
|
|
async with shared.scan_lock:
|
|
await hass.async_add_executor_job(shared.catalog.scan)
|
|
async_dispatcher_send(hass, SIGNAL_CATALOG_UPDATED)
|
|
|
|
|
|
async def async_start_catalog(hass: HomeAssistant, shared: NinlightShared) -> None:
|
|
if shared.unsub_scan is not None:
|
|
return
|
|
|
|
async def _scheduled_scan(_now: datetime) -> None:
|
|
await async_scan_catalog(hass, shared)
|
|
|
|
shared.unsub_scan = async_track_time_interval(
|
|
hass,
|
|
_scheduled_scan,
|
|
CATALOG_SCAN_INTERVAL,
|
|
name="ninlight firmware catalog",
|
|
cancel_on_shutdown=True,
|
|
)
|
|
await async_scan_catalog(hass, shared)
|
|
|
|
|
|
@callback
|
|
def async_stop_catalog(shared: NinlightShared) -> None:
|
|
if shared.unsub_scan is not None:
|
|
shared.unsub_scan()
|
|
shared.unsub_scan = None
|