117 lines
3.5 KiB
Python
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": []}
|