Scheduler (resolves #1)
This commit is contained in:
48
main.py
48
main.py
@@ -2,6 +2,7 @@ import asyncio
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Optional, List
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
@@ -9,9 +10,11 @@ from sqlalchemy import select
|
||||
|
||||
from app.core.discovery import DiscoveryService
|
||||
from app.core.state import state_manager
|
||||
from app.core.scheduler import start_scheduler, scheduler, execute_lamp_command
|
||||
from app.drivers.wiz import WizDriver
|
||||
from app.core.database import init_db, async_session
|
||||
from app.models.device import GroupModel, DeviceModel, GroupCreateSchema
|
||||
from app.models.schedule import ScheduleTask
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s"
|
||||
@@ -29,6 +32,8 @@ async def lifespan(app: FastAPI):
|
||||
await init_db()
|
||||
logger.info("🗄️ База данных инициализирована")
|
||||
|
||||
await start_scheduler()
|
||||
|
||||
# 2. Загрузка групп из БД в память
|
||||
async with async_session() as session:
|
||||
result = await session.execute(select(GroupModel))
|
||||
@@ -223,6 +228,49 @@ async def blink_device(device_id: str):
|
||||
return {"status": "blink_sent"}
|
||||
|
||||
|
||||
@app.post("/schedules/once")
|
||||
async def add_once_task(device_id: str, minutes: int, state: bool):
|
||||
device = state_manager.devices.get(device_id)
|
||||
if not device:
|
||||
raise HTTPException(status_code=404, detail="Лампа не найдена")
|
||||
|
||||
# Получаем TZ из самого шедулера, чтобы они были синхронны
|
||||
run_time = datetime.now(scheduler.timezone) + timedelta(minutes=minutes)
|
||||
|
||||
job = scheduler.add_job(
|
||||
execute_lamp_command,
|
||||
"date",
|
||||
run_date=run_time,
|
||||
args=[device.ip, {"state": state}],
|
||||
)
|
||||
|
||||
return {"status": "scheduled", "job_id": job.id, "run_at": run_time.isoformat()}
|
||||
|
||||
|
||||
@app.get("/schedules/active")
|
||||
async def get_active_jobs():
|
||||
jobs = []
|
||||
for job in scheduler.get_jobs():
|
||||
jobs.append(
|
||||
{
|
||||
"id": job.id,
|
||||
"next_run": job.next_run_time,
|
||||
"func": job.func_ref,
|
||||
"args": str(job.args),
|
||||
}
|
||||
)
|
||||
return {"active_jobs": jobs}
|
||||
|
||||
|
||||
@app.delete("/schedules/{job_id}")
|
||||
async def cancel_task(job_id: str):
|
||||
try:
|
||||
scheduler.remove_job(job_id)
|
||||
return {"status": "deleted"}
|
||||
except:
|
||||
raise HTTPException(status_code=404, detail="Задача не найдена")
|
||||
|
||||
|
||||
# --- МОНТИРОВАНИЕ СТАТИКИ (ДОЛЖНО БЫТЬ ПОСЛЕ ВСЕХ API МАРШРУТОВ) ---
|
||||
|
||||
app.mount("/", StaticFiles(directory="static", html=True), name="static")
|
||||
|
||||
Reference in New Issue
Block a user