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
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

All notable changes to this project will be documented in this file.

## [0.5.1] - 2025-08-31

### Changed

- Created a base class based on AirOS8 for both v6 and v8 to consume increasing mypy options for consumption

## [0.5.0] - Not released

Initial support for firmware 6

### Added

- Add logging redacted data on interface [issue](https://github.com/home-assistant/core/issues/151348)
- W.r.t. reported NanoBeam 8.7.18; Mark mtu optional on interfaces
- W.r.t. reported NanoStation 6.3.16-22; Provide preliminary status reporting

## [0.4.4] - 2025-08-29

### Changed
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ if __name__ == "__main__":

## Supported API classes and calls

Note: For firmware 6 we only support the login and status calls currently.

### Classes

- `airos.data` (directly) as well as `airos.airos8` (indirectly) provides `AirOSData`, a [mashumaro](https://pypi.org/project/mashumaro/) based dataclass
Expand Down
82 changes: 82 additions & 0 deletions airos/airos6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Ubiquiti AirOS 6."""

from __future__ import annotations

import logging
from typing import Any

from aiohttp import ClientSession

from .base import AirOS
from .data import AirOS6Data, DerivedWirelessRole
from .exceptions import AirOSNotSupportedError

_LOGGER = logging.getLogger(__name__)


class AirOS6(AirOS[AirOS6Data]):
"""AirOS 6 connection class."""

def __init__(
self,
host: str,
username: str,
password: str,
session: ClientSession,
use_ssl: bool = True,
) -> None:
"""Initialize AirOS8 class."""
super().__init__(
data_model=AirOS6Data,
host=host,
username=username,
password=password,
session=session,
use_ssl=use_ssl,
)

@staticmethod
def derived_wireless_data(
derived: dict[str, Any], response: dict[str, Any]
) -> dict[str, Any]:
"""Add derived wireless data to the device response."""
# Access Point / Station - no info on ptp/ptmp
# assuming ptp for station mode
derived["ptp"] = True
wireless_mode = response.get("wireless", {}).get("mode", "")
match wireless_mode:
case "ap":
derived["access_point"] = True
derived["role"] = DerivedWirelessRole.ACCESS_POINT
case "sta":
derived["station"] = True

return derived

async def update_check(self, force: bool = False) -> dict[str, Any]:
"""Check for firmware updates. Not supported on AirOS6."""
raise AirOSNotSupportedError("Firmware update check not supported on AirOS6.")

async def stakick(self, mac_address: str | None = None) -> bool:
"""Kick a station off the AP. Not supported on AirOS6."""
raise AirOSNotSupportedError("Station kick not supported on AirOS6.")

async def provmode(self, active: bool = False) -> bool:
"""Enable/Disable provisioning mode. Not supported on AirOS6."""
raise AirOSNotSupportedError("Provisioning mode not supported on AirOS6.")

async def warnings(self) -> dict[str, Any]:
"""Get device warnings. Not supported on AirOS6."""
raise AirOSNotSupportedError("Device warnings not supported on AirOS6.")

async def progress(self) -> dict[str, Any]:
"""Get firmware progress. Not supported on AirOS6."""
raise AirOSNotSupportedError("Firmware progress not supported on AirOS6.")

async def download(self) -> dict[str, Any]:
"""Download the device firmware. Not supported on AirOS6."""
raise AirOSNotSupportedError("Firmware download not supported on AirOS6.")

async def install(self) -> dict[str, Any]:
"""Install a firmware update. Not supported on AirOS6."""
raise AirOSNotSupportedError("Firmware install not supported on AirOS6.")
Loading