Files
home-automation/apps/ui/api_client.py

117 lines
3.5 KiB
Python

"""
HTTP Client for fetching devices from the API Gateway.
"""
import logging
from typing import Optional
import httpx
logger = logging.getLogger(__name__)
def fetch_devices(api_base: str) -> list[dict]:
"""
Fetch devices from the API Gateway.
Args:
api_base: Base URL of the API Gateway (e.g., "http://localhost:8001" or "http://api:8001")
Returns:
List of device dictionaries. Each device contains at least:
- device_id (str): Unique device identifier
- type (str): Device type (e.g., "light")
- name (str): Human-readable device name
Returns empty list on error.
"""
url = f"{api_base}/devices"
try:
response = httpx.get(url, timeout=3.0)
response.raise_for_status()
devices = response.json()
# API returns a list directly
if not isinstance(devices, list):
logger.warning(f"Unexpected response format from {url}: expected list, got {type(devices)}")
return []
logger.info(f"Fetched {len(devices)} devices from API Gateway")
return devices
except httpx.TimeoutException:
logger.warning(f"Timeout while fetching devices from {url}")
return []
except httpx.HTTPStatusError as e:
logger.warning(f"HTTP error {e.response.status_code} while fetching devices from {url}")
return []
except httpx.RequestError as e:
logger.warning(f"Request error while fetching devices from {url}: {e}")
return []
except Exception as e:
logger.warning(f"Unexpected error while fetching devices from {url}: {e}")
return []
def fetch_layout(api_base: str) -> dict:
"""
Fetch UI layout from the API Gateway.
Args:
api_base: Base URL of the API Gateway (e.g., "http://localhost:8001" or "http://api:8001")
Returns:
Layout dictionary with structure:
{
"rooms": [
{
"name": str,
"devices": [
{
"device_id": str,
"title": str,
"icon": str,
"rank": int
}
]
}
]
}
Returns empty layout on error.
"""
url = f"{api_base}/layout"
try:
response = httpx.get(url, timeout=3.0)
response.raise_for_status()
layout = response.json()
# API returns a dict with "rooms" key
if not isinstance(layout, dict) or "rooms" not in layout:
logger.warning(f"Unexpected response format from {url}: expected dict with 'rooms', got {type(layout)}")
return {"rooms": []}
logger.info(f"Fetched layout with {len(layout['rooms'])} rooms from API Gateway")
return layout
except httpx.TimeoutException:
logger.warning(f"Timeout while fetching layout from {url}")
return {"rooms": []}
except httpx.HTTPStatusError as e:
logger.warning(f"HTTP error {e.response.status_code} while fetching layout from {url}")
return {"rooms": []}
except httpx.RequestError as e:
logger.warning(f"Request error while fetching layout from {url}: {e}")
return {"rooms": []}
except Exception as e:
logger.warning(f"Unexpected error while fetching layout from {url}: {e}")
return {"rooms": []}