dynamic dashboard initial
This commit is contained in:
116
apps/ui/api_client.py
Normal file
116
apps/ui/api_client.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
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 = "http://localhost:8001") -> list[dict]:
|
||||
"""
|
||||
Fetch devices from the API Gateway.
|
||||
|
||||
Args:
|
||||
api_base: Base URL of the API Gateway (default: http://localhost: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 = "http://localhost:8001") -> dict:
|
||||
"""
|
||||
Fetch UI layout from the API Gateway.
|
||||
|
||||
Args:
|
||||
api_base: Base URL of the API Gateway (default: http://localhost: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": []}
|
||||
Reference in New Issue
Block a user