Files
banban/talkingq-url/main.py
2026-04-26 20:07:41 +08:00

134 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from services import offline_audio_cache
from services.device_config import DeviceConfigManager
from services.schedule_session_cleanup import background_cleanup_task
from services.role_manager import role_manager
from services.task_manager import task_manager
from initialization import register_services, init_directories
from config import settings
from utils.logger import session_logger
from api import api_router
from api.assets import configure_static_assets
from database.init_db import init_db
from database.connection import get_db_manager
from services.firmware_scanner import firmware_scanner
from handlers.mqtt_handler import TalkingQMQTTService
from services.scheduler import TaskScheduler
device_config_manager = DeviceConfigManager()
@asynccontextmanager
async def lifespan(app: FastAPI):
worker_id = os.environ.get("UVICORN_WID", "0")
is_main_process = worker_id == "0"
if is_main_process:
session_logger.system_info(
"startup",
f"服务器启动HTTP服务地址: http://{settings.server_host}:{settings.server_port}",
)
init_directories()
scheduler = TaskScheduler.get_instance()
scheduler.start()
scheduler.add_interval_task(
interval_seconds=settings.talkingq_mqtt_nfc_notice_interval
)
if settings.talkingq_mqtt_broker:
mqtt_config = {
"broker": settings.talkingq_mqtt_broker,
"port": settings.talkingq_mqtt_port,
"username": settings.talkingq_mqtt_username,
"password": settings.talkingq_mqtt_password,
"device_prefix": settings.talkingq_mqtt_device_prefix,
"qos": settings.talkingq_mqtt_qos,
"keepalive": settings.talkingq_mqtt_keepalive,
"nfc_notice_interval": settings.talkingq_mqtt_nfc_notice_interval,
}
service = await TalkingQMQTTService.get_instance(mqtt_config)
await service.connect()
session_logger.system_info("startup", "TalkingQ MQTT 设备命令服务链接已启动")
else:
session_logger.system_info("startup", "未配置 TalkingQ_MQTTMQTT 服务链接未启动")
exit(1)
try:
session_logger.system_info("startup", "初始化数据库...")
await init_db()
session_logger.system_info("startup", "数据库初始化和迁移完成")
except Exception as e:
session_logger.system_info("startup", f"数据库初始化失败: {str(e)}")
await role_manager.initialize()
await register_services()
try:
await firmware_scanner.scan_firmware_files()
session_logger.system_info("startup", "固件文件扫描完成")
except Exception as e:
session_logger.system_info("startup", f"固件文件扫描失败: {str(e)}")
session_logger.system_info("startup", "中断处理服务已初始化")
cleanup_task = asyncio.create_task(background_cleanup_task())
try:
yield
finally:
cleanup_task.cancel()
try:
await asyncio.wait_for(cleanup_task, timeout=5.0)
except (asyncio.CancelledError, asyncio.TimeoutError):
if is_main_process:
session_logger.system_info("shutdown", "后台清理任务已取消")
from services.audio_session import audio_session_manager
sessions_to_close = []
async for session_key, session in audio_session_manager.get_all_sessions():
sessions_to_close.append((session_key, session))
for session_key, session in sessions_to_close:
try:
if session.send_task:
session.send_task.cancel()
if hasattr(session, "asr_service") and session.asr_service:
await session.asr_service.close()
if hasattr(session, "llm_service") and session.llm_service:
await session.llm_service.close()
except Exception as e:
if is_main_process:
session_logger.system_info("shutdown", f"清理会话时出错: {str(e)}")
# 清理所有任务管理器的任务
try:
await task_manager.cleanup_all_tasks()
if is_main_process:
session_logger.system_info("shutdown", "任务管理器清理完成")
except Exception as e:
if is_main_process:
session_logger.system_info("shutdown", f"任务管理器清理时出错: {str(e)}")
try:
db_manager = await get_db_manager()
await db_manager.close()
if is_main_process:
session_logger.system_info("shutdown", "数据库连接已关闭")
except Exception as e:
if is_main_process:
session_logger.system_info("shutdown", f"关闭数据库连接时出错: {str(e)}")
TaskScheduler.reset_instance()
await TalkingQMQTTService.reset_instance()
session_logger.system_info("shutdown", "TalkingQ MQTT 服务链接已关闭")
if is_main_process:
session_logger.system_info("shutdown", "应用关闭")
app = FastAPI(lifespan=lifespan)
configure_static_assets(app)
app.include_router(api_router)