feat: Pydantic schemas and EMQX REST API client
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
41
src/mqtt_home/emqx_api.py
Normal file
41
src/mqtt_home/emqx_api.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import httpx
|
||||
from typing import Any
|
||||
|
||||
from mqtt_home.config import Settings
|
||||
|
||||
|
||||
class EmqxApiClient:
|
||||
def __init__(self, settings: Settings):
|
||||
self._client = httpx.AsyncClient(
|
||||
base_url=settings.emqx_api_url,
|
||||
auth=(settings.emqx_api_key, settings.emqx_api_secret),
|
||||
timeout=10.0,
|
||||
)
|
||||
|
||||
async def close(self):
|
||||
await self._client.aclose()
|
||||
|
||||
async def get_broker_status(self) -> dict[str, Any]:
|
||||
resp = await self._client.get("/status")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", {})
|
||||
|
||||
async def get_metrics(self) -> dict[str, Any]:
|
||||
resp = await self._client.get("/metrics")
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", {})
|
||||
|
||||
async def get_clients(self, limit: int = 100) -> list[dict[str, Any]]:
|
||||
resp = await self._client.get("/clients", params={"limit": limit})
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
async def get_subscriptions(self, limit: int = 100) -> list[dict[str, Any]]:
|
||||
resp = await self._client.get("/subscriptions", params={"limit": limit})
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
|
||||
async def get_topics(self, limit: int = 100) -> list[dict[str, Any]]:
|
||||
resp = await self._client.get("/topics", params={"limit": limit})
|
||||
resp.raise_for_status()
|
||||
return resp.json().get("data", [])
|
||||
70
src/mqtt_home/schemas.py
Normal file
70
src/mqtt_home/schemas.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class DeviceCreate(BaseModel):
|
||||
name: str
|
||||
type: str = "switch"
|
||||
protocol: str = "custom"
|
||||
mqtt_topic: str
|
||||
command_topic: Optional[str] = None
|
||||
|
||||
|
||||
class DeviceUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
type: Optional[str] = None
|
||||
command_topic: Optional[str] = None
|
||||
|
||||
|
||||
class DeviceCommand(BaseModel):
|
||||
payload: str
|
||||
|
||||
|
||||
class DeviceResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
type: str
|
||||
protocol: str
|
||||
mqtt_topic: str
|
||||
command_topic: Optional[str] = None
|
||||
state: Optional[str] = None
|
||||
is_online: bool
|
||||
last_seen: Optional[datetime] = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class DeviceLogResponse(BaseModel):
|
||||
id: int
|
||||
device_id: str
|
||||
direction: str
|
||||
topic: str
|
||||
payload: str
|
||||
timestamp: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class BrokerClient(BaseModel):
|
||||
clientid: str
|
||||
username: Optional[str] = None
|
||||
ip_address: Optional[str] = None
|
||||
connected: bool
|
||||
keepalive: int
|
||||
proto_ver: Optional[int] = None
|
||||
clean_start: Optional[bool] = None
|
||||
|
||||
|
||||
class BrokerTopic(BaseModel):
|
||||
topic: str
|
||||
node: Optional[str] = None
|
||||
|
||||
|
||||
class DashboardStats(BaseModel):
|
||||
total_devices: int
|
||||
online_devices: int
|
||||
offline_devices: int
|
||||
recent_logs: list[DeviceLogResponse]
|
||||
Reference in New Issue
Block a user