work: добавил автоматический режим

This commit is contained in:
Fedorov Dmitriy
2026-09-18 23:59:42 +03:00
parent 7dbfd8b069
commit cdec9b0996
24 changed files with 3449 additions and 33 deletions
+113 -19
View File
@@ -7,6 +7,9 @@ from fastapi.responses import JSONResponse
from app.my_dataclasses import (
TION_MAC,
QINGPING_MAC,
QINGPING_MQTT_HOST,
QINGPING_MQTT_PORT,
MIN_FAN_SPEED,
MAX_FAN_SPEED,
MIN_TARGET_TEMP,
@@ -14,6 +17,13 @@ from app.my_dataclasses import (
AIR_MODE_OUTSIDE,
AIR_MODE_RECIRCULATION,
SCHEDULE_FILE,
AUTO_CONFIG_FILE,
)
from app.auto import (
AutoController,
Co2SpeedPolicy,
load_auto_config,
)
from app.tion import (
@@ -27,7 +37,7 @@ from schedule import (
load_schedule,
)
from app.qingping.service import QingpingService
def configure_logging() -> None:
noisy_loggers = (
@@ -57,9 +67,19 @@ service = TionService(
controller,
poll_interval=5,
)
qingping_service = QingpingService(
host=QINGPING_MQTT_HOST,
port=QINGPING_MQTT_PORT,
mac=QINGPING_MAC,
)
schedule_service: ScheduleService | None = None
schedule_load_error: str | None = None
auto_controller: AutoController | None = None
auto_load_error: str | None = None
# ----------------------------------------------------------------------
# Application lifecycle
# ----------------------------------------------------------------------
@@ -68,8 +88,11 @@ schedule_load_error: str | None = None
async def lifespan(app: FastAPI):
global schedule_service
global schedule_load_error
global auto_controller
global auto_load_error
await service.start()
await qingping_service.start()
try:
try:
@@ -84,6 +107,50 @@ async def lifespan(app: FastAPI):
await schedule_service.start()
schedule_load_error = None
try:
auto_config = load_auto_config(
AUTO_CONFIG_FILE
)
auto_policy = Co2SpeedPolicy(
base_speed=(
auto_config.co2.base_speed
),
thresholds=(
auto_config.co2.thresholds
),
hysteresis=(
auto_config.co2.hysteresis
),
)
auto_interval = (
auto_config.check_interval
)
auto_load_error = None
except Exception as exc:
auto_policy = None
# Безопасный встроенный интервал нужен,
# потому что auto.yaml сейчас недоступен.
auto_interval = 5.0
auto_load_error = (
f"{type(exc).__name__}: {exc}"
)
auto_controller = AutoController(
schedule_service=schedule_service,
qingping_service=qingping_service,
tion_service=service,
policy=auto_policy,
interval=auto_interval,
)
await auto_controller.start()
except Exception as exc:
schedule_service = None
schedule_load_error = f"{type(exc).__name__}: {exc}"
@@ -93,6 +160,7 @@ async def lifespan(app: FastAPI):
if schedule_service is not None:
await schedule_service.stop()
await qingping_service.stop()
await service.stop()
@@ -152,6 +220,8 @@ def get_status() -> dict:
else None
),
"qingping": qingping_service.status(),
"schedule": get_schedule_status(),
}
@@ -349,6 +419,30 @@ def get_schedule_status() -> dict:
),
}
def get_auto_status() -> dict:
if auto_controller is None:
return {
"available": False,
"state": "unavailable",
"reason": None,
"target_speed": None,
"auto_speed": None,
"last_error": None,
"config_error": (
auto_load_error
),
}
return {
"available": True,
**auto_controller.status(),
"config_error": (
auto_load_error
),
}
# ----------------------------------------------------------------------
# Status
# ----------------------------------------------------------------------
@@ -401,24 +495,6 @@ async def increase_speed():
),
)
# ----------------------------------------------------------------------
# Fan speed
# ----------------------------------------------------------------------
@app.post("/api/tion/speed/{speed}")
async def set_speed(
speed: Annotated[
int,
Path(
ge=MIN_FAN_SPEED,
le=MAX_FAN_SPEED,
),
] ):
return await execute_command(
lambda tion: tion.set_speed(speed),
ScheduledSettings(speed=speed),
)
@app.post("/api/tion/speed/decrease")
async def decrease_speed():
@@ -440,6 +516,24 @@ async def decrease_speed():
)
# ----------------------------------------------------------------------
# Fan speed
# ----------------------------------------------------------------------
@app.post("/api/tion/speed/{speed}")
async def set_speed(
speed: Annotated[
int,
Path(
ge=MIN_FAN_SPEED,
le=MAX_FAN_SPEED,
),
] ):
return await execute_command(
lambda tion: tion.set_speed(speed),
ScheduledSettings(speed=speed),
)
# ----------------------------------------------------------------------
# Heater
# ----------------------------------------------------------------------