diff --git a/src/mqtt_home/__main__.py b/src/mqtt_home/__main__.py new file mode 100644 index 0000000..06706f0 --- /dev/null +++ b/src/mqtt_home/__main__.py @@ -0,0 +1,3 @@ +from mqtt_home.cli import cli + +cli() diff --git a/src/mqtt_home/cli.py b/src/mqtt_home/cli.py index 6b4cae5..f6f2f9b 100644 --- a/src/mqtt_home/cli.py +++ b/src/mqtt_home/cli.py @@ -1,6 +1,11 @@ import asyncio +import sys import click +# Windows compatibility: use SelectorEventLoop for paho-mqtt +if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + from mqtt_home.config import get_settings from mqtt_home.database import init_db, get_session_factory from mqtt_home.emqx_api import EmqxApiClient diff --git a/src/mqtt_home/emqx_api.py b/src/mqtt_home/emqx_api.py index 1ff8066..8269f74 100644 --- a/src/mqtt_home/emqx_api.py +++ b/src/mqtt_home/emqx_api.py @@ -18,12 +18,25 @@ class EmqxApiClient: async def get_broker_status(self) -> dict[str, Any]: resp = await self._client.get("/status") resp.raise_for_status() - return resp.json().get("data", {}) + # /status may return plain text, try JSON first + try: + data = resp.json() + if isinstance(data, dict) and "data" in data: + return data["data"] + return data if isinstance(data, dict) else {"raw": resp.text} + except Exception: + return {"raw": resp.text} async def get_metrics(self) -> dict[str, Any]: resp = await self._client.get("/metrics") resp.raise_for_status() - return resp.json().get("data", {}) + data = resp.json() + # /metrics returns a list in some EMQX versions + if isinstance(data, list) and data: + return data[0] if isinstance(data[0], dict) else {} + if isinstance(data, dict) and "data" in data: + return data["data"] if isinstance(data["data"], dict) else {} + return data if isinstance(data, dict) else {} async def get_clients(self, limit: int = 100) -> list[dict[str, Any]]: resp = await self._client.get("/clients", params={"limit": limit}) diff --git a/src/mqtt_home/main.py b/src/mqtt_home/main.py index c5447ee..f3ee40c 100644 --- a/src/mqtt_home/main.py +++ b/src/mqtt_home/main.py @@ -1,7 +1,12 @@ import asyncio import logging +import sys from contextlib import asynccontextmanager +# Windows compatibility: use SelectorEventLoop for paho-mqtt (add_reader/add_writer) +if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware diff --git a/tests/test_config.py b/tests/test_config.py index d7c1847..5aa8bb6 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -3,7 +3,7 @@ from mqtt_home.config import Settings def test_default_settings(): - s = Settings() + s = Settings(_env_file=None) assert s.mqtt_host == "localhost" assert s.mqtt_port == 1883 assert s.web_port == 8000