fix: Windows event loop compatibility, EMQX API response handling, and test fix

- Add WindowsSelectorEventLoopPolicy for paho-mqtt on Windows
- Handle EMQX /status plain text and /metrics list responses
- Fix test_default_settings to ignore .env file
- Add __main__.py for python -m mqtt_home support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
walkpan
2026-03-29 21:52:20 +08:00
parent bac099c805
commit c4d35be54d
5 changed files with 29 additions and 3 deletions

View File

@@ -0,0 +1,3 @@
from mqtt_home.cli import cli
cli()

View File

@@ -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

View File

@@ -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})

View File

@@ -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

View File

@@ -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