Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions aiohasupervisor/homeassistant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Home Assistant client for supervisor."""

from .client import _SupervisorComponentClient
from .models.homeassistant import (
HomeAssistantInfo,
HomeAssistantOptions,
HomeAssistantRebuildOptions,
HomeAssistantRestartOptions,
HomeAssistantStats,
HomeAssistantStopOptions,
HomeAssistantUpdateOptions,
)


class HomeAssistantClient(_SupervisorComponentClient):
"""Handles Home Assistant access in supervisor."""

async def info(self) -> HomeAssistantInfo:
"""Get Home Assistant info."""
result = await self._client.get("core/info")
return HomeAssistantInfo.from_dict(result.data)

async def stats(self) -> HomeAssistantStats:
"""Get Home Assistant stats."""
result = await self._client.get("core/stats")
return HomeAssistantStats.from_dict(result.data)

async def options(self, options: HomeAssistantOptions) -> None:
"""Set Home Assistant options."""
await self._client.post("core/options", json=options.to_dict())

async def update(self, options: HomeAssistantUpdateOptions | None = None) -> None:
"""Update Home Assistant."""
await self._client.post(
"core/update", json=options.to_dict() if options else None
)

async def restart(self, options: HomeAssistantRestartOptions | None = None) -> None:
"""Restart Home Assistant."""
await self._client.post(
"core/restart", json=options.to_dict() if options else None
)

async def stop(self, options: HomeAssistantStopOptions | None = None) -> None:
"""Stop Home Assistant."""
await self._client.post(
"core/stop", json=options.to_dict() if options else None
)

async def start(self) -> None:
"""Start Home Assistant."""
await self._client.post("core/start")

async def check_config(self) -> None:
"""Check Home Assistant config."""
await self._client.post("core/check")

async def rebuild(self, options: HomeAssistantRebuildOptions | None = None) -> None:
"""Rebuild Home Assistant."""
await self._client.post(
"core/rebuild", json=options.to_dict() if options else None
)
16 changes: 16 additions & 0 deletions aiohasupervisor/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@
StoreInfo,
SupervisorRole,
)
from aiohasupervisor.models.homeassistant import (
HomeAssistantInfo,
HomeAssistantOptions,
HomeAssistantRebuildOptions,
HomeAssistantRestartOptions,
HomeAssistantStats,
HomeAssistantStopOptions,
HomeAssistantUpdateOptions,
)
from aiohasupervisor.models.resolution import (
Check,
CheckOptions,
Expand Down Expand Up @@ -96,4 +105,11 @@
"SupervisorOptions",
"SupervisorStats",
"SupervisorUpdateOptions",
"HomeAssistantInfo",
"HomeAssistantOptions",
"HomeAssistantRebuildOptions",
"HomeAssistantRestartOptions",
"HomeAssistantStats",
"HomeAssistantStopOptions",
"HomeAssistantUpdateOptions",
]
13 changes: 2 additions & 11 deletions aiohasupervisor/models/addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from mashumaro import field_options
from mashumaro.config import TO_DICT_ADD_BY_ALIAS_FLAG, BaseConfig

from .base import DEFAULT, Options, Request, RequestConfig, ResponseData
from .base import DEFAULT, ContainerStats, Options, Request, RequestConfig, ResponseData

# --- ENUMS ----

Expand Down Expand Up @@ -296,18 +296,9 @@ class AddonsSecurityOptions(Options):


@dataclass(frozen=True, slots=True)
class AddonsStats(ResponseData):
class AddonsStats(ContainerStats):
"""AddonsStats model."""

cpu_percent: float
memory_usage: int
memory_limit: int
memory_percent: float
network_rx: int
network_tx: int
blk_read: int
blk_write: int


@dataclass(frozen=True, slots=True)
class AddonsUninstall(Request):
Expand Down
79 changes: 79 additions & 0 deletions aiohasupervisor/models/homeassistant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""Models for Home Assistant."""

from dataclasses import dataclass
from ipaddress import IPv4Address

from .base import DEFAULT, ContainerStats, Options, Request, ResponseData

# --- OBJECTS ----


@dataclass(frozen=True, slots=True)
class HomeAssistantInfo(ResponseData):
"""HomeAssistantInfo model."""

version: str | None
version_latest: str | None
update_available: bool
machine: str
ip_address: IPv4Address
arch: str
image: str
boot: bool
port: int
ssl: bool
watchdog: bool
audio_input: str
audio_output: str
backups_exclude_database: bool


@dataclass(frozen=True, slots=True)
class HomeAssistantStats(ContainerStats):
"""HomeAssistantStats model."""


@dataclass(frozen=True, slots=True)
class HomeAssistantOptions(Options):
"""HomeAssistantOptions model."""

boot: bool | None = None
image: str | None = DEFAULT # type: ignore[assignment]
port: int | None = None
ssl: bool | None = None
watchdog: bool | None = None
refresh_token: str | None = DEFAULT # type: ignore[assignment]
audio_input: str | None = DEFAULT # type: ignore[assignment]
audio_output: str | None = DEFAULT # type: ignore[assignment]
backups_exclude_database: bool | None = None


@dataclass(frozen=True, slots=True)
class HomeAssistantUpdateOptions(Options):
"""HomeAssistantUpdateOptions model."""

version: str | None = None
backup: bool | None = None


@dataclass(frozen=True, slots=True)
class HomeAssistantRestartOptions(Options):
"""HomeAssistantRestartOptions model."""

safe_mode: bool | None = None
force: bool | None = None


@dataclass(frozen=True, slots=True)
class HomeAssistantRebuildOptions(Options):
"""HomeAssistantRebuildOptions model."""

safe_mode: bool | None = None
force: bool | None = None


@dataclass(frozen=True, slots=True)
class HomeAssistantStopOptions(Request):
"""HomeAssistantStopOptions model."""

force: bool
7 changes: 7 additions & 0 deletions aiohasupervisor/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from .addons import AddonsClient
from .client import _SupervisorClient
from .homeassistant import HomeAssistantClient
from .models.root import AvailableUpdate, AvailableUpdates, RootInfo
from .resolution import ResolutionClient
from .store import StoreClient
Expand All @@ -28,12 +29,18 @@ def __init__(
self._resolution = ResolutionClient(self._client)
self._store = StoreClient(self._client)
self._supervisor = SupervisorManagementClient(self._client)
self._homeassistant = HomeAssistantClient(self._client)

@property
def addons(self) -> AddonsClient:
"""Get addons component client."""
return self._addons

@property
def homeassistant(self) -> HomeAssistantClient:
"""Get Home Assistant component client."""
return self._homeassistant

@property
def resolution(self) -> ResolutionClient:
"""Get resolution center component client."""
Expand Down
19 changes: 19 additions & 0 deletions tests/fixtures/homeassistant_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"result": "ok",
"data": {
"version": "2024.9.0",
"version_latest": "2024.9.0",
"update_available": false,
"machine": "odroid-n2",
"ip_address": "172.30.32.1",
"arch": "aarch64",
"image": "ghcr.io/home-assistant/odroid-n2-homeassistant",
"boot": true,
"port": 8123,
"ssl": false,
"watchdog": true,
"audio_input": null,
"audio_output": null,
"backups_exclude_database": false
}
}
13 changes: 13 additions & 0 deletions tests/fixtures/homeassistant_stats.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"result": "ok",
"data": {
"cpu_percent": 0.01,
"memory_usage": 678883328,
"memory_limit": 3899138048,
"memory_percent": 17.41,
"network_rx": 0,
"network_tx": 0,
"blk_read": 0,
"blk_write": 0
}
}
Loading
Loading