add homekit_aid and load it
All checks were successful
ci/woodpecker/tag/build/5 Pipeline was successful
ci/woodpecker/tag/build/6 Pipeline was successful
ci/woodpecker/tag/build/4 Pipeline was successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
ci/woodpecker/tag/build/7 Pipeline was successful
ci/woodpecker/tag/build/3 Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/deploy/1 Pipeline was successful
ci/woodpecker/tag/deploy/4 Pipeline was successful
ci/woodpecker/tag/deploy/3 Pipeline was successful
ci/woodpecker/tag/deploy/2 Pipeline was successful
ci/woodpecker/tag/deploy/6 Pipeline was successful
ci/woodpecker/tag/deploy/5 Pipeline was successful
ci/woodpecker/tag/ingress Pipeline was successful
All checks were successful
ci/woodpecker/tag/build/5 Pipeline was successful
ci/woodpecker/tag/build/6 Pipeline was successful
ci/woodpecker/tag/build/4 Pipeline was successful
ci/woodpecker/tag/namespace Pipeline was successful
ci/woodpecker/tag/build/1 Pipeline was successful
ci/woodpecker/tag/config Pipeline was successful
ci/woodpecker/tag/build/7 Pipeline was successful
ci/woodpecker/tag/build/3 Pipeline was successful
ci/woodpecker/tag/build/2 Pipeline was successful
ci/woodpecker/tag/deploy/1 Pipeline was successful
ci/woodpecker/tag/deploy/4 Pipeline was successful
ci/woodpecker/tag/deploy/3 Pipeline was successful
ci/woodpecker/tag/deploy/2 Pipeline was successful
ci/woodpecker/tag/deploy/6 Pipeline was successful
ci/woodpecker/tag/deploy/5 Pipeline was successful
ci/woodpecker/tag/ingress Pipeline was successful
This commit is contained in:
@@ -51,6 +51,9 @@ logger = logging.getLogger(__name__)
|
||||
# Will be populated from Redis pub/sub messages
|
||||
device_states: dict[str, dict[str, Any]] = {}
|
||||
|
||||
# Devices configuration cache (loaded once at startup)
|
||||
devices_cache: list[dict[str, Any]] = []
|
||||
|
||||
# Background task reference
|
||||
background_task: asyncio.Task | None = None
|
||||
|
||||
@@ -117,15 +120,6 @@ async def get_device_layout(device_id: str):
|
||||
}
|
||||
raise HTTPException(status_code=404, detail="Device layout not found")
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""Include routers after app is initialized to avoid circular imports."""
|
||||
from apps.api.routes.groups_scenes import router as groups_scenes_router
|
||||
from apps.api.routes.rooms import router as rooms_router
|
||||
|
||||
app.include_router(groups_scenes_router, prefix="")
|
||||
app.include_router(rooms_router, prefix="")
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health() -> dict[str, str]:
|
||||
@@ -190,7 +184,22 @@ async def redis_state_listener():
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""Start background tasks on application startup."""
|
||||
global background_task
|
||||
global background_task, devices_cache
|
||||
|
||||
# Include routers
|
||||
from apps.api.routes.groups_scenes import router as groups_scenes_router
|
||||
from apps.api.routes.rooms import router as rooms_router
|
||||
|
||||
app.include_router(groups_scenes_router, prefix="")
|
||||
app.include_router(rooms_router, prefix="")
|
||||
|
||||
# Load and validate devices configuration
|
||||
try:
|
||||
devices_cache = load_devices_from_file()
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to load devices configuration: {e}")
|
||||
raise # Fatal error - application will not start
|
||||
|
||||
background_task = asyncio.create_task(redis_state_listener())
|
||||
logger.info("Started background Redis state listener")
|
||||
|
||||
@@ -238,32 +247,62 @@ class DeviceInfo(BaseModel):
|
||||
device_id: str
|
||||
type: str
|
||||
name: str
|
||||
homekit_aid: int
|
||||
features: dict[str, Any] = {}
|
||||
|
||||
|
||||
# Configuration helpers
|
||||
def load_devices() -> list[dict[str, Any]]:
|
||||
"""Load devices from configuration file.
|
||||
def load_devices_from_file() -> list[dict[str, Any]]:
|
||||
"""Load devices from configuration file and validate.
|
||||
|
||||
Returns:
|
||||
list: List of device configurations
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If devices.yaml doesn't exist
|
||||
KeyError: If any device is missing required homekit_aid field
|
||||
ValueError: If devices.yaml is invalid or contains duplicate homekit_aid values
|
||||
"""
|
||||
config_path = Path(__file__).parent.parent.parent / "config" / "devices.yaml"
|
||||
|
||||
if not config_path.exists():
|
||||
return []
|
||||
raise FileNotFoundError(f"devices.yaml not found at {config_path}")
|
||||
|
||||
with open(config_path, "r") as f:
|
||||
config = yaml.safe_load(f)
|
||||
|
||||
if not config or "devices" not in config:
|
||||
raise ValueError("devices.yaml must contain 'devices' key")
|
||||
|
||||
# Normalize device entries: accept both 'id' and 'device_id', use 'device_id' internally
|
||||
devices = config.get("devices", [])
|
||||
for device in devices:
|
||||
device["device_id"] = device.pop("device_id", device.pop("id", None))
|
||||
|
||||
# Validate required homekit_aid field
|
||||
if "homekit_aid" not in device:
|
||||
raise KeyError(f"Device {device.get('device_id', 'unknown')} is missing required 'homekit_aid' field")
|
||||
|
||||
# Validate unique homekit_aid values
|
||||
aids = [d["homekit_aid"] for d in devices]
|
||||
if len(aids) != len(set(aids)):
|
||||
duplicates = [aid for aid in aids if aids.count(aid) > 1]
|
||||
raise ValueError(f"Duplicate homekit_aid values found: {set(duplicates)}")
|
||||
|
||||
logger.info(f"Loaded {len(devices)} devices with unique homekit_aid values (range: {min(aids)}-{max(aids)})")
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
def load_devices() -> list[dict[str, Any]]:
|
||||
"""Get devices from in-memory cache.
|
||||
|
||||
Returns:
|
||||
list: List of device configurations (loaded at startup)
|
||||
"""
|
||||
return devices_cache
|
||||
|
||||
|
||||
def get_mqtt_settings() -> tuple[str, int]:
|
||||
"""Get MQTT broker settings from environment.
|
||||
|
||||
@@ -391,6 +430,7 @@ async def get_device(device_id: str) -> DeviceInfo:
|
||||
device_id=device["device_id"],
|
||||
type=device["type"],
|
||||
name=device.get("name", device["device_id"]),
|
||||
homekit_aid=device["homekit_aid"],
|
||||
features=device.get("features", {})
|
||||
)
|
||||
|
||||
@@ -409,6 +449,7 @@ async def get_devices() -> list[DeviceInfo]:
|
||||
device_id=device["device_id"],
|
||||
type=device["type"],
|
||||
name=device.get("name", device["device_id"]),
|
||||
homekit_aid=device["homekit_aid"],
|
||||
features=device.get("features", {})
|
||||
)
|
||||
for device in devices
|
||||
|
||||
Reference in New Issue
Block a user