http_server.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import asyncio
  2. from aiohttp import web
  3. from config.logger import setup_logging
  4. from core.api.app_gps_handler import AppGpsHandler
  5. from core.api.ota_handler import OTAHandler
  6. from core.api.vision_handler import VisionHandler
  7. TAG = __name__
  8. class SimpleHttpServer:
  9. def __init__(self, config: dict, ws_server=None):
  10. self.config = config
  11. self.logger = setup_logging()
  12. self.ws_server = ws_server
  13. self.app_gps_handler = AppGpsHandler(config, ws_server) if ws_server else None
  14. self.ota_handler = OTAHandler(config)
  15. self.vision_handler = VisionHandler(config)
  16. def _get_websocket_url(self, local_ip: str, port: int) -> str:
  17. """获取websocket地址
  18. Args:
  19. local_ip: 本地IP地址
  20. port: 端口号
  21. Returns:
  22. str: websocket地址
  23. """
  24. server_config = self.config["server"]
  25. websocket_config = server_config.get("websocket")
  26. if websocket_config and "你" not in websocket_config:
  27. return websocket_config
  28. else:
  29. return f"ws://{local_ip}:{port}/xiaozhi/v1/"
  30. async def start(self):
  31. try:
  32. server_config = self.config["server"]
  33. read_config_from_api = self.config.get("read_config_from_api", False)
  34. host = server_config.get("ip", "0.0.0.0")
  35. port = int(server_config.get("http_port", 8003))
  36. if port:
  37. app = web.Application()
  38. if not read_config_from_api:
  39. # 如果没有开启智控台,只是单模块运行,就需要再添加简单OTA接口,用于下发websocket接口
  40. app.add_routes(
  41. [
  42. web.get("/xiaozhi/ota/", self.ota_handler.handle_get),
  43. web.post("/xiaozhi/ota/", self.ota_handler.handle_post),
  44. web.options(
  45. "/xiaozhi/ota/", self.ota_handler.handle_options
  46. ),
  47. # 下载接口,仅提供 data/bin/*.bin 下载
  48. web.get(
  49. "/xiaozhi/ota/download/{filename}",
  50. self.ota_handler.handle_download,
  51. ),
  52. web.options(
  53. "/xiaozhi/ota/download/{filename}",
  54. self.ota_handler.handle_options,
  55. ),
  56. ]
  57. )
  58. # 添加路由
  59. app.add_routes(
  60. [
  61. web.get("/mcp/vision/explain", self.vision_handler.handle_get),
  62. web.post(
  63. "/mcp/vision/explain", self.vision_handler.handle_post
  64. ),
  65. web.options(
  66. "/mcp/vision/explain", self.vision_handler.handle_options
  67. ),
  68. ]
  69. )
  70. # 运行服务
  71. if self.app_gps_handler:
  72. app.add_routes(
  73. [
  74. web.get("/app/gps/latest", self.app_gps_handler.handle_get_latest),
  75. web.get("/app/gps/ws", self.app_gps_handler.handle_ws),
  76. web.get("/app/risk-alerts", self.app_gps_handler.handle_get_risk_alerts),
  77. web.post("/app/risk-alerts", self.app_gps_handler.handle_post_risk_alerts),
  78. web.delete("/app/risk-alerts/{alert_id}", self.app_gps_handler.handle_delete_risk_alert),
  79. web.options("/app/gps/latest", self.app_gps_handler.handle_options),
  80. web.options("/app/gps/ws", self.app_gps_handler.handle_options),
  81. web.options("/app/risk-alerts", self.app_gps_handler.handle_options),
  82. web.options("/app/risk-alerts/{alert_id}", self.app_gps_handler.handle_options),
  83. ]
  84. )
  85. runner = web.AppRunner(app)
  86. await runner.setup()
  87. site = web.TCPSite(runner, host, port)
  88. await site.start()
  89. # 保持服务运行
  90. while True:
  91. await asyncio.sleep(3600) # 每隔 1 小时检查一次
  92. except Exception as e:
  93. self.logger.bind(tag=TAG).error(f"HTTP服务器启动失败: {e}")
  94. import traceback
  95. self.logger.bind(tag=TAG).error(f"错误堆栈: {traceback.format_exc()}")
  96. raise