diff --git a/app.py b/app.py index ef33c17a..e7949885 100644 --- a/app.py +++ b/app.py @@ -2,8 +2,7 @@ import asyncio from config.logger import setup_logging from config.settings import load_config from core.websocket_server import WebSocketServer -from manager.http_server import ConfigServer -from core.webui import WebUI +from manager.http_server import WebUI from aiohttp import web from core.utils.util import get_local_ip @@ -14,37 +13,29 @@ async def main(): # 启动 WebSocket 服务器 ws_server = WebSocketServer(config) ws_task = asyncio.create_task(ws_server.start()) - - # 启动 HTTP 配置服务器 - http_runner = None - if config['manager'].get('enabled', False): - config_server = ConfigServer(config) - try: - http_runner = await config_server.start() - except Exception as e: - print(f"Failed to start HTTP server: {e}") - + # 启动 WebUI 服务器 webui_runner = None - try: - webui = WebUI() - runner = web.AppRunner(webui.app) - await runner.setup() - site = web.TCPSite(runner, '0.0.0.0', 8002) - await site.start() - webui_runner = runner - local_ip = get_local_ip() - print(f"WebUI server is running at http://{local_ip}:8002") - except Exception as e: - print(f"Failed to start WebUI server: {e}") + if config['manager'].get('enabled', False): + server_config = config["manager"] + host = server_config["ip"] + port = server_config["port"] + try: + webui = WebUI() + runner = web.AppRunner(webui.app) + await runner.setup() + site = web.TCPSite(runner, host, port) + await site.start() + webui_runner = runner + local_ip = get_local_ip() + print(f"WebUI server is running at http://{local_ip}:{port}") + except Exception as e: + print(f"Failed to start WebUI server: {e}") try: # 等待 WebSocket 服务器运行 await ws_task finally: - # 清理 HTTP 服务器 - if http_runner: - await http_runner.cleanup() # 清理 WebUI 服务器 if webui_runner: await webui_runner.cleanup() diff --git a/config.yaml b/config.yaml index a7644adf..e09a50c5 100644 --- a/config.yaml +++ b/config.yaml @@ -22,11 +22,11 @@ server: #allowed_devices: # - "24:0A:C4:1D:3B:F0" # MAC地址列表 manager: + # 是否启用管理后台 + # 目前这个模块还在开发中,建议:不要修改enabled选项 enabled: false ip: 0.0.0.0 - port: 8001 - # 请把密码设置10位数,且不能包含xiaozhi这几个字符 - password: 123456 + port: 8002 xiaozhi: type: hello diff --git a/core/webui.py b/core/webui.py deleted file mode 100644 index 82b0f316..00000000 --- a/core/webui.py +++ /dev/null @@ -1,90 +0,0 @@ -import os -import sys -import logging -from aiohttp import web -from aiohttp_cors import setup as cors_setup, ResourceOptions -from core.utils.util import get_local_ip - -# 添加项目根目录到Python路径 -current_dir = os.path.dirname(os.path.abspath(__file__)) -root_dir = os.path.dirname(current_dir) -sys.path.append(root_dir) - -from manager.api.login import LoginHandler -from manager.api.register import RegisterHandler -from manager.user_manager import UserManager -from manager.api.config import ConfigHandler - -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -class WebUI: - def __init__(self): - self.app = web.Application() - self.user_manager = UserManager() - - # 添加静态文件路径 - self.static_path = os.path.join(root_dir, 'manager', 'static', 'webui') - - # 创建配置字典 - self.config = { - 'users': self.user_manager.get_users(), - 'hash_password': self.user_manager.hash_password, - 'save_user_data': self.user_manager.save_user_data, - 'get_user': self.user_manager.get_user, - 'update_user': self.user_manager.update_user - } - - self.setup_routes() - self.setup_cors() - - def setup_cors(self): - """设置CORS""" - cors = cors_setup(self.app, defaults={ - "*": ResourceOptions( - allow_credentials=True, - expose_headers="*", - allow_headers="*", - allow_methods="*" - ) - }) - - for route in list(self.app.router.routes()): - cors.add(route) - - def setup_routes(self): - """设置路由""" - login_handler = LoginHandler(self.config) - register_handler = RegisterHandler(self.config) - config_handler = ConfigHandler() - - # API 路由 - self.app.router.add_post('/api/login', login_handler.handle_login) - self.app.router.add_post('/api/register', register_handler.handle_register) - self.app.router.add_get('/api/config/devices', config_handler.get_private_configs) - self.app.router.add_post('/api/config/device', config_handler.save_device_config) - self.app.router.add_get('/api/config/module-options', config_handler.get_module_options) - self.app.router.add_post('/api/config/save_device_config', config_handler.save_device_config) - self.app.router.add_post('/api/config/delete_device', config_handler.delete_device_config) - - # 添加静态文件服务 - self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets')) - # 所有未匹配的路由都返回 index.html - self.app.router.add_get('/{tail:.*}', self.handle_static_files) - - async def handle_static_files(self, request): - """处理静态文件请求,支持SPA前端路由""" - index_file = os.path.join(self.static_path, 'index.html') - if os.path.exists(index_file): - return web.FileResponse(index_file) - return web.Response(status=404, text='Not found') - - def run(self, host='0.0.0.0', port=8002): - """运行服务器""" - local_ip = get_local_ip() - logger.info(f"WebUI server is running at http://{local_ip}:{port}") - web.run_app(self.app, host=host, port=port) - -if __name__ == '__main__': - webui = WebUI() - webui.run() diff --git a/manager/http_server.py b/manager/http_server.py index 6157a7c8..82b0f316 100644 --- a/manager/http_server.py +++ b/manager/http_server.py @@ -1,92 +1,90 @@ -import logging import os +import sys +import logging from aiohttp import web -from core.utils.util import get_local_ip, get_project_dir, check_password -from manager.api.prompt import PromptApi -from manager.api.auth import AuthApi -from aiohttp.web_middlewares import middleware +from aiohttp_cors import setup as cors_setup, ResourceOptions +from core.utils.util import get_local_ip +# 添加项目根目录到Python路径 +current_dir = os.path.dirname(os.path.abspath(__file__)) +root_dir = os.path.dirname(current_dir) +sys.path.append(root_dir) + +from manager.api.login import LoginHandler +from manager.api.register import RegisterHandler +from manager.user_manager import UserManager +from manager.api.config import ConfigHandler + +logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) - -@middleware -async def cors_middleware(request, handler): - # 预检请求处理 - if request.method == 'OPTIONS': - return web.Response( - status=204, - headers={ - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Authorization, Token', - 'Access-Control-Max-Age': '86400', - } - ) - - try: - response = await handler(request) - except web.HTTPException as ex: - response = ex - - # 添加CORS头到所有响应 - cors_headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Expose-Headers': 'Content-Type, Authorization, Token', - 'Vary': 'Origin' # 避免缓存问题 - } - response.headers.update(cors_headers) - - return response - - -class ConfigServer: - def __init__(self, config: dict): - self.config = config - self.app = web.Application(middlewares=[cors_middleware]) # 注册中间件 - - # 初始化接口处理器 - self.prompt_handler = PromptApi(config) - self.auth_handler = AuthApi(config) +class WebUI: + def __init__(self): + self.app = web.Application() + self.user_manager = UserManager() + + # 添加静态文件路径 + self.static_path = os.path.join(root_dir, 'manager', 'static', 'webui') + + # 创建配置字典 + self.config = { + 'users': self.user_manager.get_users(), + 'hash_password': self.user_manager.hash_password, + 'save_user_data': self.user_manager.save_user_data, + 'get_user': self.user_manager.get_user, + 'update_user': self.user_manager.update_user + } + self.setup_routes() + self.setup_cors() + + def setup_cors(self): + """设置CORS""" + cors = cors_setup(self.app, defaults={ + "*": ResourceOptions( + allow_credentials=True, + expose_headers="*", + allow_headers="*", + allow_methods="*" + ) + }) + + for route in list(self.app.router.routes()): + cors.add(route) def setup_routes(self): - # 注册prompt接口 - self.app.router.add_get('/api/prompt', self.prompt_handler.get_prompt) - self.app.router.add_post('/api/prompt', self.prompt_handler.update_prompt) + """设置路由""" + login_handler = LoginHandler(self.config) + register_handler = RegisterHandler(self.config) + config_handler = ConfigHandler() + + # API 路由 + self.app.router.add_post('/api/login', login_handler.handle_login) + self.app.router.add_post('/api/register', register_handler.handle_register) + self.app.router.add_get('/api/config/devices', config_handler.get_private_configs) + self.app.router.add_post('/api/config/device', config_handler.save_device_config) + self.app.router.add_get('/api/config/module-options', config_handler.get_module_options) + self.app.router.add_post('/api/config/save_device_config', config_handler.save_device_config) + self.app.router.add_post('/api/config/delete_device', config_handler.delete_device_config) - # 注册auth接口 - self.app.router.add_post('/api/login', self.auth_handler.login) + # 添加静态文件服务 + self.app.router.add_static('/assets/', path=os.path.join(self.static_path, 'assets')) + # 所有未匹配的路由都返回 index.html + self.app.router.add_get('/{tail:.*}', self.handle_static_files) - # 注册静态文件路由 - static_dir = os.path.join(get_project_dir(), 'manager/static') # 获取static目录绝对路径 - self.app.router.add_static( - prefix='/manager/', # 匹配前缀 - path=static_dir, # 静态文件目录 - name='static' - ) - self.app.router.add_get('/manager', self.redirect_to_index) + async def handle_static_files(self, request): + """处理静态文件请求,支持SPA前端路由""" + index_file = os.path.join(self.static_path, 'index.html') + if os.path.exists(index_file): + return web.FileResponse(index_file) + return web.Response(status=404, text='Not found') - async def redirect_to_index(self, _): - raise web.HTTPFound('/manager/') + def run(self, host='0.0.0.0', port=8002): + """运行服务器""" + local_ip = get_local_ip() + logger.info(f"WebUI server is running at http://{local_ip}:{port}") + web.run_app(self.app, host=host, port=port) - async def start(self): - try: - http_config = self.config['manager'] - if not http_config.get('enabled', False): - logger.info("HTTP server is disabled") - return - token = self.config['manager']['token'] - if not check_password(token): - logger.info("您设置的后台密码太弱了,启动后台管理失败!") - return - - runner = web.AppRunner(self.app) - await runner.setup() - site = web.TCPSite(runner, http_config['ip'], http_config['port']) - await site.start() - logger.info( - f"Config HTTP server is running at http://{get_local_ip()}:{http_config['port']}/manager/login.html") - return runner # 返回runner以便后续清理 - except Exception as e: - logger.error(f"Failed to start HTTP server: {e}") - raise +if __name__ == '__main__': + webui = WebUI() + webui.run()