Skip to content

Commit

Permalink
Add core APIs to client library (#15)
Browse files Browse the repository at this point in the history
* Add core APIs to client library

* Use IPv4Address for ip address

* Separate rebuild options and test passing options

* Use rebuild options
  • Loading branch information
mdegat01 authored Oct 9, 2024
1 parent 31cbaed commit d04e78c
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 11 deletions.
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

0 comments on commit d04e78c

Please sign in to comment.