# app/api/dashboard.py from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel from typing import List, Dict, Any, Optional from app.core.security import require_auth from app.core.vad import get_vad_instance, get_stt_instance from app.core.status import status_tracker from app.core.system_monitor import get_system_load router = APIRouter(prefix="/api/dashboard", tags=["dashboard"]) class SpeechData(BaseModel): state: str speech_prob: float speech_threshold: float # Добавлено: порог обнаружения речи energy: float energy_threshold: float speech_detected: bool # Добавлено: признак обнаружения речи continuous_frames: int # Добавлено: количество непрерывных кадров речи gain: float # Добавлено: текущий коэффициент усиления noise_floor: float # Добавлено: уровень шума class RecognizedPhrase(BaseModel): text: str timestamp: str action: str = None class SystemLoad(BaseModel): # Добавлено: модель для системной нагрузки cpu_percent: float memory_percent: float temperature: float @router.get("/speech-data", response_model=SpeechData) async def get_speech_data(request: Request, token: str = Depends(require_auth)): """Получение текущих данных о речи и энергии, включая расширенные метрики VAD и STT""" try: vad = get_vad_instance(request) if not vad: return SpeechData( state=status_tracker.get_status(), speech_prob=0.0, speech_threshold=0.0, energy=0, energy_threshold=0, speech_detected=False, continuous_frames=0, gain=1.0, noise_floor=0.0, ) # Получаем данные из last_result VAD last_result = vad.last_result # Дополнительные атрибуты VAD (на основе класса VADPolling) gain = vad.current_gain noise_floor = vad.noise_floor continuous_frames = last_result.get('continuous_frames', vad.continuous_speech_frames) # Если есть в last_result или атрибуте return SpeechData( state=status_tracker.get_status(), speech_prob=float(last_result.get('speech_ratio', 0.0)), speech_threshold=float(last_result.get('speech_threshold', 0.0)), energy=float(last_result.get('energy', 0)), energy_threshold=float(last_result.get('energy_threshold', 0)), speech_detected=bool(last_result.get('speech_detected', False)), continuous_frames=int(continuous_frames), gain=float(gain), noise_floor=float(noise_floor), ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/sys-monitor", response_model=SystemLoad) # Добавлено: новый эндпоинт async def get_sys_monitor(token: str = Depends(require_auth)): """Получение данных о нагрузке системы (CPU, память, температура)""" try: load_data = get_system_load() return SystemLoad(**load_data) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/recent-phrases", response_model=List[RecognizedPhrase]) async def get_recent_phrases(request: Request, limit: int = 10, token: str = Depends(require_auth)): """Получение последних распознанных фраз""" try: stt = get_stt_instance(request) if not stt or not hasattr(stt, 'get_history'): from app.core.history import get_recognition_history phrases = get_recognition_history(limit) else: phrases = stt.get_history(limit) return phrases except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.get("/stats", response_model=Dict[str, Any]) async def get_stats(request: Request, token: str = Depends(require_auth)): """Получение статистики работы системы""" try: # Здесь будет логика получения статистики работы системы # Например, количество распознанных команд, время работы и т.д. return { "uptime": "0:00:00", # Будет заменено на реальное время работы "recognized_phrases_count": 0, "commands_executed_count": 0, "system_load": 0.0 } except Exception as e: raise HTTPException(status_code=500, detail=str(e))