- LinkResponse/UnknownClientResponse Pydantic schemas with from_attributes - Link service with get_links, get_device_links, get_site_links, get_unknown_clients - Unknown clients query uses DISTINCT ON for latest registration per MAC - 4 REST endpoints: tenant links, device links, site links, unknown clients - Interface and link discovery subscribers wired into FastAPI lifespan start/stop - Links router registered at /api prefix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 lines
1.4 KiB
Python
57 lines
1.4 KiB
Python
"""Pydantic schemas for Link and Unknown Client endpoints."""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
class LinkResponse(BaseModel):
|
|
"""Single wireless link between an AP and CPE device."""
|
|
|
|
id: uuid.UUID
|
|
ap_device_id: uuid.UUID
|
|
cpe_device_id: uuid.UUID
|
|
ap_hostname: str | None = None
|
|
cpe_hostname: str | None = None
|
|
interface: str | None = None
|
|
client_mac: str
|
|
signal_strength: int | None = None
|
|
tx_ccq: int | None = None
|
|
tx_rate: str | None = None
|
|
rx_rate: str | None = None
|
|
state: str
|
|
missed_polls: int
|
|
discovered_at: datetime
|
|
last_seen: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class LinkListResponse(BaseModel):
|
|
"""List of wireless links with total count."""
|
|
|
|
items: list[LinkResponse]
|
|
total: int
|
|
|
|
|
|
class UnknownClientResponse(BaseModel):
|
|
"""A wireless client whose MAC does not resolve to any known device interface."""
|
|
|
|
mac_address: str
|
|
interface: str | None = None
|
|
signal_strength: int | None = None
|
|
tx_rate: str | None = None
|
|
rx_rate: str | None = None
|
|
last_seen: datetime
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
class UnknownClientListResponse(BaseModel):
|
|
"""List of unknown clients with total count."""
|
|
|
|
items: list[UnknownClientResponse]
|
|
total: int
|