from __future__ import annotations import os from dataclasses import dataclass from dotenv import load_dotenv load_dotenv() @dataclass(frozen=True) class Settings: stream_url: str api_base_url: str app_id: str app_secret: str device_list_path: str device_account: str stream_method: str detr_model: str confidence: float frame_skip: int jpeg_quality: int resize_width: int | None vehicle_labels: set[str] def _optional_int(name: str) -> int | None: value = os.getenv(name, "").strip() if not value: return None parsed = int(value) return parsed if parsed > 0 else None def load_settings() -> Settings: stream_url = os.getenv("STREAM_URL", "").strip() vehicle_labels = { item.strip() for item in os.getenv("VEHICLE_LABELS", "car,motorcycle,bus,truck,bicycle").split(",") if item.strip() } return Settings( stream_url=stream_url, api_base_url=os.getenv("API_BASE_URL", "https://apicapacity.51iwifi.com"), app_id=os.getenv("APP_ID", ""), app_secret=os.getenv("APP_SECRET", ""), device_list_path=os.getenv("DEVICE_LIST_PATH", "devicelist.env"), device_account=os.getenv("DEVICE_ACCOUNT", "21cn"), stream_method=os.getenv("STREAM_METHOD", "capacity.geye.device.devUrl.get"), detr_model=os.getenv("DETR_MODEL", "facebook/detr-resnet-50"), confidence=float(os.getenv("DETR_CONFIDENCE", "0.6")), frame_skip=max(1, int(os.getenv("FRAME_SKIP", "3"))), jpeg_quality=min(100, max(1, int(os.getenv("JPEG_QUALITY", "80")))), resize_width=_optional_int("RESIZE_WIDTH"), vehicle_labels=vehicle_labels, ) def mask_url(url: str) -> str: if "token=" not in url: return url prefix, _ = url.split("token=", 1) return f"{prefix}token=***"