Bootstrap SillyHome Future v2 core
This commit is contained in:
113
app/main.py
Normal file
113
app/main.py
Normal file
@@ -0,0 +1,113 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from app.core.event_core import EventCore
|
||||
from app.core.handoff import HandoffMatrix
|
||||
from app.core.models import (
|
||||
AuditEvent,
|
||||
BackupBundle,
|
||||
ControlProfile,
|
||||
ControlState,
|
||||
HandoffMode,
|
||||
LearningState,
|
||||
RuntimeState,
|
||||
StateEvent,
|
||||
)
|
||||
from app.core.stores import FutureStores
|
||||
|
||||
app = FastAPI(
|
||||
title="SillyHome Future API",
|
||||
description="SillyHome v2 event-core side project.",
|
||||
version="2.0.0-alpha.1",
|
||||
)
|
||||
stores = FutureStores(os.getenv("SILLYHOME_FUTURE_STORE", ".future_store"))
|
||||
event_core = EventCore(stores)
|
||||
handoff = HandoffMatrix()
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> dict[str, str]:
|
||||
return {"status": "ok", "version": app.version}
|
||||
|
||||
|
||||
@app.post("/v2/events/state", response_model=list[AuditEvent])
|
||||
def ingest_state_event(event: StateEvent) -> list[AuditEvent]:
|
||||
return event_core.process_state_event(event)
|
||||
|
||||
|
||||
@app.get("/v2/runtime", response_model=RuntimeState)
|
||||
def get_runtime() -> RuntimeState:
|
||||
return stores.runtime()
|
||||
|
||||
|
||||
@app.get("/v2/learning", response_model=LearningState)
|
||||
def get_learning() -> LearningState:
|
||||
return stores.learning()
|
||||
|
||||
|
||||
@app.put("/v2/learning", response_model=LearningState)
|
||||
def put_learning(state: LearningState) -> LearningState:
|
||||
return stores.save_learning(state)
|
||||
|
||||
|
||||
@app.get("/v2/control", response_model=ControlState)
|
||||
def get_control() -> ControlState:
|
||||
return stores.control()
|
||||
|
||||
|
||||
@app.put("/v2/control/{actuator_entity_id}", response_model=ControlProfile)
|
||||
def put_control(actuator_entity_id: str, profile: ControlProfile) -> ControlProfile:
|
||||
state = stores.control()
|
||||
state.profiles[actuator_entity_id] = profile
|
||||
stores.save_control(state)
|
||||
return profile
|
||||
|
||||
|
||||
@app.post("/v2/handoff/{actuator_entity_id}/assume", response_model=ControlProfile)
|
||||
def assume_control(actuator_entity_id: str) -> ControlProfile:
|
||||
state = stores.control()
|
||||
profile = state.profiles.get(
|
||||
actuator_entity_id,
|
||||
ControlProfile(actuator_entity_id=actuator_entity_id),
|
||||
)
|
||||
updated = handoff.assume_control(profile)
|
||||
state.profiles[actuator_entity_id] = updated
|
||||
stores.save_control(state)
|
||||
return updated
|
||||
|
||||
|
||||
@app.post("/v2/handoff/{actuator_entity_id}/rollback", response_model=ControlProfile)
|
||||
def rollback_control(actuator_entity_id: str) -> ControlProfile:
|
||||
state = stores.control()
|
||||
profile = state.profiles.get(
|
||||
actuator_entity_id,
|
||||
ControlProfile(actuator_entity_id=actuator_entity_id),
|
||||
)
|
||||
updated = handoff.rollback(profile)
|
||||
state.profiles[actuator_entity_id] = updated
|
||||
stores.save_control(state)
|
||||
return updated
|
||||
|
||||
|
||||
@app.get("/v2/handoff/{actuator_entity_id}", response_model=HandoffMode)
|
||||
def classify_handoff(actuator_entity_id: str) -> HandoffMode:
|
||||
profile = stores.control().profiles.get(
|
||||
actuator_entity_id,
|
||||
ControlProfile(actuator_entity_id=actuator_entity_id),
|
||||
)
|
||||
return handoff.classify(profile)
|
||||
|
||||
|
||||
@app.get("/v2/backup/export", response_model=BackupBundle)
|
||||
def export_backup() -> BackupBundle:
|
||||
return stores.export_backup()
|
||||
|
||||
|
||||
@app.post("/v2/backup/restore")
|
||||
def restore_backup(bundle: BackupBundle) -> dict[str, str]:
|
||||
stores.restore_backup(bundle)
|
||||
return {"status": "restored"}
|
||||
|
||||
Reference in New Issue
Block a user