BEHAVIOR-001: learn and predict actuator actions
This commit is contained in:
34
app/main.py
34
app/main.py
@@ -12,8 +12,7 @@ from app.actuators.lifecycle import ActuatorReconciliationService
|
||||
from app.actuators.store import ActuatorStore
|
||||
from app.api.v1.actuators import router as actuators_router
|
||||
from app.api.v1.entities import router as entities_router
|
||||
from app.api.v1.automations import router as automations_router
|
||||
from app.automations.store import AutomationStore
|
||||
from app.behavior.engine import BehaviorEngine
|
||||
from app.config import load_settings
|
||||
from app.core.exception_handlers import register_exception_handlers
|
||||
from app.ha.client import HaClient, HaClientSettings
|
||||
@@ -27,13 +26,15 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
settings = app.state.settings
|
||||
client: HaClient | None = None
|
||||
reconcile_task: asyncio.Task[None] | None = None
|
||||
prediction_task: asyncio.Task[None] | None = None
|
||||
app.state.registry = ModelRegistry(settings.model_store)
|
||||
app.state.automation_store = AutomationStore(settings.automation_store)
|
||||
app.state.actuator_store = ActuatorStore(settings.actuator_store)
|
||||
if hasattr(app.state, "ha_reader"):
|
||||
del app.state.ha_reader
|
||||
if hasattr(app.state, "actuator_service"):
|
||||
del app.state.actuator_service
|
||||
if hasattr(app.state, "behavior_engine"):
|
||||
del app.state.behavior_engine
|
||||
if settings.ha_configured:
|
||||
client = HaClient(
|
||||
settings=HaClientSettings(
|
||||
@@ -48,8 +49,16 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
registry=app.state.registry,
|
||||
settings=settings,
|
||||
)
|
||||
app.state.behavior_engine = BehaviorEngine(
|
||||
ha_reader=app.state.ha_reader,
|
||||
store=app.state.actuator_store,
|
||||
settings=settings,
|
||||
)
|
||||
await asyncio.to_thread(app.state.actuator_service.reconcile_all, "startup")
|
||||
await asyncio.to_thread(app.state.behavior_engine.train_all)
|
||||
await asyncio.to_thread(app.state.behavior_engine.evaluate_all)
|
||||
reconcile_task = asyncio.create_task(_periodic_reconciliation(app))
|
||||
prediction_task = asyncio.create_task(_periodic_prediction(app))
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
@@ -57,6 +66,10 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
reconcile_task.cancel()
|
||||
with suppress(asyncio.CancelledError):
|
||||
await reconcile_task
|
||||
if prediction_task is not None:
|
||||
prediction_task.cancel()
|
||||
with suppress(asyncio.CancelledError):
|
||||
await prediction_task
|
||||
if client is not None:
|
||||
client.close()
|
||||
|
||||
@@ -64,13 +77,12 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
app = FastAPI(
|
||||
title="SillyHome Next API",
|
||||
description="Lokales Smart-Home-Intelligenzsystem für Home Assistant.",
|
||||
version="0.4.0",
|
||||
version="0.5.0",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
app.state.settings = load_settings()
|
||||
register_exception_handlers(app)
|
||||
app.include_router(entities_router)
|
||||
app.include_router(automations_router)
|
||||
app.include_router(actuators_router)
|
||||
init_ml_routes(app, model_store=app.state.settings.model_store)
|
||||
|
||||
@@ -95,3 +107,15 @@ async def _periodic_reconciliation(app: FastAPI) -> None:
|
||||
if not isinstance(service, ActuatorReconciliationService):
|
||||
continue
|
||||
await asyncio.to_thread(service.reconcile_all, "scheduled")
|
||||
engine = getattr(app.state, "behavior_engine", None)
|
||||
if isinstance(engine, BehaviorEngine):
|
||||
await asyncio.to_thread(engine.train_all)
|
||||
|
||||
|
||||
async def _periodic_prediction(app: FastAPI) -> None:
|
||||
while True:
|
||||
await asyncio.sleep(app.state.settings.prediction_interval_seconds)
|
||||
engine = getattr(app.state, "behavior_engine", None)
|
||||
if not isinstance(engine, BehaviorEngine):
|
||||
continue
|
||||
await asyncio.to_thread(engine.evaluate_all)
|
||||
|
||||
Reference in New Issue
Block a user