From 7d9f44d124c2471e99a58124d76595d0d7b6c66a Mon Sep 17 00:00:00 2001 From: zhaozilong12 <405241463@qq.com> Date: Tue, 29 Jul 2025 18:28:40 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DEBUG_GUIDE.md | 243 ++++++++++ backend/app.py | 133 ++++-- debug_server.py | 138 ++++++ frontend/src/renderer/src/views/Detection.vue | 3 - frontend_websocket_example.html | 383 ++++++++++++++++ javascript_websocket_example.js | 382 ++++++++++++++++ start_debug.bat | 100 +++++ test_websocket.py | 53 +++ vue_websocket_example.vue | 421 ++++++++++++++++++ 9 files changed, 1825 insertions(+), 31 deletions(-) create mode 100644 DEBUG_GUIDE.md create mode 100644 debug_server.py create mode 100644 frontend_websocket_example.html create mode 100644 javascript_websocket_example.js create mode 100644 start_debug.bat create mode 100644 test_websocket.py create mode 100644 vue_websocket_example.vue diff --git a/DEBUG_GUIDE.md b/DEBUG_GUIDE.md new file mode 100644 index 00000000..1eecf38b --- /dev/null +++ b/DEBUG_GUIDE.md @@ -0,0 +1,243 @@ +# 调试指南 + +本文档介绍如何在开发过程中进行调试,包括断点调试、日志调试等方法。 + +## 调试方式概览 + +### 1. 批处理文件调试 (推荐新手) +```bash +# 启动调试模式 +./start_debug.bat +``` + +### 2. Python脚本调试 (推荐) +```bash +# 直接运行调试服务器 +python debug_server.py +``` + +### 3. VS Code调试 (推荐开发者) +- 打开VS Code +- 按F5或点击调试按钮 +- 选择"Debug Backend Server"配置 + +### 4. 命令行调试 +```bash +# 激活虚拟环境 +backend\venv\Scripts\activate + +# 设置环境变量 +set FLASK_ENV=development +set FLASK_DEBUG=1 +set PYTHONPATH=%cd% + +# 启动调试服务器 +python -u backend\app.py +``` + +## 详细调试方法 + +### VS Code 断点调试 + +1. **安装Python扩展** + - 确保VS Code已安装Python扩展 + +2. **打开项目** + ```bash + code . + ``` + +3. **设置断点** + - 在代码行号左侧点击设置断点 + - 红色圆点表示断点已设置 + +4. **启动调试** + - 按F5或点击调试面板的播放按钮 + - 选择"Debug Backend Server"配置 + +5. **调试操作** + - F10: 单步跳过 + - F11: 单步进入 + - Shift+F11: 单步跳出 + - F5: 继续执行 + - Shift+F5: 停止调试 + +### PyCharm 调试 + +1. **打开项目** + - File -> Open -> 选择项目目录 + +2. **配置Python解释器** + - File -> Settings -> Project -> Python Interpreter + - 选择backend/venv/Scripts/python.exe + +3. **创建运行配置** + - Run -> Edit Configurations + - 添加新的Python配置 + - Script path: debug_server.py + - Working directory: 项目根目录 + +4. **设置断点并调试** + - 点击行号左侧设置断点 + - 点击调试按钮启动 + +### 命令行调试 + +1. **使用pdb调试器** + ```python + import pdb + pdb.set_trace() # 在需要调试的地方插入 + ``` + +2. **使用ipdb (增强版pdb)** + ```bash + pip install ipdb + ``` + ```python + import ipdb + ipdb.set_trace() + ``` + +## 调试配置说明 + +### 环境变量 +- `FLASK_ENV=development`: 启用开发模式 +- `FLASK_DEBUG=1`: 启用调试模式 +- `PYTHONPATH`: 设置Python模块搜索路径 + +### 调试端口 +- 后端服务: http://127.0.0.1:5000 +- 健康检查: http://127.0.0.1:5000/health +- WebSocket: ws://127.0.0.1:5000/socket.io/ + +## 常见调试场景 + +### 1. WebSocket连接问题 +```python +# 在handle_connect函数中设置断点 +@socketio.on('connect') +def handle_connect(): + print(f'客户端连接: {request.sid}') # 添加调试输出 + # 设置断点在这里 + emit('connect_status', {'status': 'connected'}) +``` + +### 2. RTSP流问题 +```python +# 在generate_rtsp_frames函数中设置断点 +def generate_rtsp_frames(): + print(f'RTSP URL: {rtsp_url}') # 调试输出 + # 设置断点检查rtsp_url值 + cap = cv2.VideoCapture(rtsp_url) +``` + +### 3. API请求问题 +```python +# 在API路由中设置断点 +@app.route('/api/patients', methods=['GET']) +def get_patients(): + print(f'请求参数: {request.args}') # 调试输出 + # 设置断点检查请求参数 +``` + +### 4. 数据库操作问题 +```python +# 在数据库操作中设置断点 +def get_patients(self, page, size, keyword): + print(f'查询参数: page={page}, size={size}, keyword={keyword}') + # 设置断点检查SQL查询 +``` + +## 日志调试 + +### 查看日志文件 +```bash +# 实时查看日志 +tail -f logs/debug.log +tail -f logs/backend.log +``` + +### 调整日志级别 +```python +# 在代码中临时调整日志级别 +import logging +logging.getLogger().setLevel(logging.DEBUG) +``` + +## 前端调试 + +### 浏览器开发者工具 +1. 按F12打开开发者工具 +2. Console标签页查看JavaScript错误 +3. Network标签页查看网络请求 +4. WebSocket连接在Network -> WS中查看 + +### 前端调试技巧 +```javascript +// 在浏览器控制台中测试WebSocket连接 +const socket = io('http://127.0.0.1:5000'); +socket.on('connect', () => console.log('连接成功')); +socket.emit('start_rtsp', {}); +``` + +## 性能调试 + +### 使用cProfile +```bash +python -m cProfile -o profile_output.prof debug_server.py +``` + +### 内存使用监控 +```bash +pip install memory-profiler +python -m memory_profiler debug_server.py +``` + +## 故障排除 + +### 常见问题 + +1. **端口被占用** + ```bash + netstat -ano | findstr :5000 + taskkill /PID /F + ``` + +2. **模块导入错误** + - 检查PYTHONPATH设置 + - 确认虚拟环境已激活 + +3. **权限问题** + - 以管理员身份运行 + - 检查文件夹权限 + +4. **依赖包问题** + ```bash + pip install -r backend/requirements.txt --force-reinstall + ``` + +### 调试检查清单 + +- [ ] Python虚拟环境已激活 +- [ ] 所有依赖包已安装 +- [ ] 环境变量设置正确 +- [ ] 端口5000未被占用 +- [ ] config.ini文件存在且配置正确 +- [ ] 日志文件可以正常写入 +- [ ] 断点设置在正确位置 + +## 调试最佳实践 + +1. **逐步调试**: 从简单的断点开始,逐步深入 +2. **日志记录**: 在关键位置添加详细的日志输出 +3. **单元测试**: 编写测试用例验证功能 +4. **代码审查**: 定期检查代码逻辑 +5. **版本控制**: 使用Git跟踪代码变更 + +## 获取帮助 + +如果遇到调试问题,可以: +1. 查看logs目录下的日志文件 +2. 检查控制台输出信息 +3. 使用浏览器开发者工具 +4. 参考项目文档和代码注释 \ No newline at end of file diff --git a/backend/app.py b/backend/app.py index 6c5780e1..281aa9ee 100644 --- a/backend/app.py +++ b/backend/app.py @@ -627,7 +627,7 @@ if __name__ == '__main__': # 启动Flask+SocketIO服务 logger.info('启动后端服务...') socketio.run(app, - host=config.get('SERVER', 'host', fallback='127.0.0.1'), + host=config.get('SERVER', 'host', fallback='0.0.0.0'), port=config.getint('SERVER', 'port', fallback=5000), debug=config.getboolean('APP', 'debug', fallback=False), allow_unsafe_werkzeug=True @@ -644,37 +644,114 @@ if __name__ == '__main__': def generate_rtsp_frames(): global rtsp_running - cap = cv2.VideoCapture(rtsp_url) - if not cap.isOpened(): - logger.error(f'无法打开RTSP流: {rtsp_url}') - return - rtsp_running = True - while rtsp_running: - ret, frame = cap.read() - if not ret: - logger.warning('RTSP读取帧失败,尝试重连...') + frame_count = 0 + error_count = 0 + + logger.info(f'开始生成RTSP帧,URL: {rtsp_url}') + + try: + cap = cv2.VideoCapture(rtsp_url) + if not cap.isOpened(): + logger.error(f'无法打开RTSP流: {rtsp_url}') + socketio.emit('rtsp_status', {'status': 'error', 'message': f'无法打开RTSP流: {rtsp_url}'}) + return + + logger.info('RTSP流已打开,开始推送帧') + rtsp_running = True + + while rtsp_running: + ret, frame = cap.read() + if not ret: + error_count += 1 + logger.warning(f'RTSP读取帧失败(第{error_count}次),尝试重连...') + cap.release() + + if error_count > 5: + logger.error('RTSP连接失败次数过多,停止推流') + socketio.emit('rtsp_status', {'status': 'error', 'message': 'RTSP连接失败次数过多'}) + break + + time.sleep(1) + cap = cv2.VideoCapture(rtsp_url) + continue + + error_count = 0 # 重置错误计数 + frame_count += 1 + + try: + _, buffer = cv2.imencode('.jpg', frame) + jpg_as_text = base64.b64encode(buffer).decode('utf-8') + socketio.emit('rtsp_frame', {'image': jpg_as_text}) + + if frame_count % 150 == 0: # 每150帧(约10秒)记录一次 + logger.info(f'已推送 {frame_count} 帧') + + except Exception as e: + logger.error(f'编码帧失败: {e}') + + time.sleep(1/15) # 推送帧率可调 + + except Exception as e: + logger.error(f'RTSP推流异常: {e}') + socketio.emit('rtsp_status', {'status': 'error', 'message': f'推流异常: {str(e)}'}) + finally: + if 'cap' in locals(): cap.release() - time.sleep(1) - cap = cv2.VideoCapture(rtsp_url) - continue - _, buffer = cv2.imencode('.jpg', frame) - jpg_as_text = base64.b64encode(buffer).decode('utf-8') - socketio.emit('rtsp_frame', {'image': jpg_as_text}) - time.sleep(1/15) # 推送帧率可调 - cap.release() + rtsp_running = False + logger.info(f'RTSP推流结束,总共推送了 {frame_count} 帧') @socketio.on('start_rtsp') -def handle_start_rtsp(): +def handle_start_rtsp(data=None): global rtsp_thread, rtsp_running - if rtsp_thread and rtsp_thread.is_alive(): - emit('rtsp_status', {'status': 'already_running'}) - return - rtsp_thread = threading.Thread(target=generate_rtsp_frames) - rtsp_thread.start() - emit('rtsp_status', {'status': 'started'}) + logger.info(f'收到start_rtsp事件,客户端ID: {request.sid}, 数据: {data}') + + try: + if rtsp_thread and rtsp_thread.is_alive(): + logger.warning('RTSP线程已在运行') + emit('rtsp_status', {'status': 'already_running', 'message': 'RTSP已在运行'}) + return + + if not rtsp_url: + logger.error('RTSP URL未配置') + emit('rtsp_status', {'status': 'error', 'message': 'RTSP URL未配置'}) + return + + logger.info(f'启动RTSP线程,URL: {rtsp_url}') + rtsp_thread = threading.Thread(target=generate_rtsp_frames) + rtsp_thread.daemon = True + rtsp_thread.start() + + logger.info('RTSP线程已启动') + emit('rtsp_status', {'status': 'started', 'message': 'RTSP推流已启动'}) + + except Exception as e: + logger.error(f'启动RTSP失败: {e}') + emit('rtsp_status', {'status': 'error', 'message': f'启动失败: {str(e)}'}) @socketio.on('stop_rtsp') -def handle_stop_rtsp(): +def handle_stop_rtsp(data=None): global rtsp_running - rtsp_running = False - emit('rtsp_status', {'status': 'stopped'}) \ No newline at end of file + logger.info(f'收到stop_rtsp事件,客户端ID: {request.sid}, 数据: {data}') + + try: + rtsp_running = False + logger.info('RTSP推流已停止') + emit('rtsp_status', {'status': 'stopped', 'message': 'RTSP推流已停止'}) + + except Exception as e: + logger.error(f'停止RTSP失败: {e}') + emit('rtsp_status', {'status': 'error', 'message': f'停止失败: {str(e)}'}) + +@socketio.on('connect') +def handle_connect(): + logger.info(f'客户端连接: {request.sid}') + emit('connect_status', {'status': 'connected', 'sid': request.sid, 'message': '连接成功'}) + +@socketio.on('disconnect') +def handle_disconnect(): + logger.info(f'客户端断开连接: {request.sid}') + +@socketio.on('ping') +def handle_ping(data=None): + logger.info(f'收到ping事件,客户端ID: {request.sid}, 数据: {data}') + emit('pong', {'timestamp': time.time(), 'message': 'pong'}) \ No newline at end of file diff --git a/debug_server.py b/debug_server.py new file mode 100644 index 00000000..2968744f --- /dev/null +++ b/debug_server.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +身体平衡评估系统 - 调试服务器启动脚本 + +这个脚本专门用于调试模式,提供更好的调试体验: +1. 支持IDE断点调试 +2. 详细的错误信息输出 +3. 热重载功能 +4. 调试日志输出 +""" + +import os +import sys +import logging +from pathlib import Path + +# 添加项目路径 +project_root = Path(__file__).parent +sys.path.insert(0, str(project_root)) +sys.path.insert(0, str(project_root / 'backend')) + +def setup_debug_logging(): + """设置调试日志""" + # 创建logs目录 + logs_dir = project_root / 'logs' + logs_dir.mkdir(exist_ok=True) + + # 配置日志格式 + logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(message)s', + handlers=[ + logging.FileHandler(logs_dir / 'debug.log', encoding='utf-8'), + logging.StreamHandler(sys.stdout) + ] + ) + + # 设置Flask和SocketIO的日志级别 + logging.getLogger('werkzeug').setLevel(logging.DEBUG) + logging.getLogger('socketio').setLevel(logging.DEBUG) + logging.getLogger('engineio').setLevel(logging.DEBUG) + + logger = logging.getLogger(__name__) + logger.info('调试日志已启用') + return logger + +def check_debug_environment(): + """检查调试环境""" + logger = logging.getLogger(__name__) + + # 检查Python版本 + if sys.version_info < (3, 8): + logger.error('需要Python 3.8或更高版本') + return False + + # 检查必要文件 + required_files = [ + 'backend/app.py', + 'backend/config.ini', + 'backend/requirements.txt' + ] + + for file_path in required_files: + if not (project_root / file_path).exists(): + logger.error(f'缺少必要文件: {file_path}') + return False + + logger.info('调试环境检查通过') + return True + +def start_debug_server(): + """启动调试服务器""" + logger = logging.getLogger(__name__) + + try: + # 设置环境变量 + os.environ['FLASK_ENV'] = 'development' + os.environ['FLASK_DEBUG'] = '1' + os.environ['PYTHONPATH'] = str(project_root) + + # 导入Flask应用 + from backend.app import app, socketio, init_app + + # 初始化应用 + logger.info('初始化应用...') + init_app() + + # 启动调试服务器 + logger.info('启动调试服务器...') + logger.info('调试模式已启用 - 可以在IDE中设置断点') + logger.info('服务器地址: http://127.0.0.1:5000') + logger.info('健康检查: http://127.0.0.1:5000/health') + logger.info('按 Ctrl+C 停止服务器') + + # 启动SocketIO服务器(支持调试) + socketio.run( + app, + host='127.0.0.1', + port=5000, + debug=True, + use_reloader=True, # 启用热重载 + log_output=True, # 输出详细日志 + allow_unsafe_werkzeug=True + ) + + except KeyboardInterrupt: + logger.info('服务器被用户中断') + except Exception as e: + logger.error(f'服务器启动失败: {e}', exc_info=True) + return False + + return True + +def main(): + """主函数""" + print('='*50) + print('身体平衡评估系统 - 调试模式') + print('='*50) + print() + + # 设置调试日志 + logger = setup_debug_logging() + + # 检查环境 + if not check_debug_environment(): + input('按任意键退出...') + sys.exit(1) + + # 启动调试服务器 + success = start_debug_server() + + if not success: + input('按任意键退出...') + sys.exit(1) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/frontend/src/renderer/src/views/Detection.vue b/frontend/src/renderer/src/views/Detection.vue index a99db0d8..7f588fe7 100644 --- a/frontend/src/renderer/src/views/Detection.vue +++ b/frontend/src/renderer/src/views/Detection.vue @@ -711,9 +711,6 @@ onUnmounted(() => { justify-content: center; color: #ffffff; font-size: 12px; -} -.gauge-group-box-left{ - } .gauge-table-title{ padding: 10px; diff --git a/frontend_websocket_example.html b/frontend_websocket_example.html new file mode 100644 index 00000000..ea7558e6 --- /dev/null +++ b/frontend_websocket_example.html @@ -0,0 +1,383 @@ + + + + + + 前端WebSocket连接示例 + + + + +
+

前端WebSocket连接示例

+ +
未连接
+ +
+ + + + +
+ +
+ + + + +
+ + + +
+

RTSP视频流

+ +
暂无视频流
+
+ +
+
+ + + + \ No newline at end of file diff --git a/javascript_websocket_example.js b/javascript_websocket_example.js new file mode 100644 index 00000000..65b7aaf9 --- /dev/null +++ b/javascript_websocket_example.js @@ -0,0 +1,382 @@ +/** + * 前端WebSocket连接示例 - JavaScript版本 + * 使用Socket.IO客户端连接Flask-SocketIO后端 + */ + +// 引入Socket.IO客户端库 +// 在HTML中添加: +// 或者使用npm安装: npm install socket.io-client + +class WebSocketManager { + constructor() { + this.socket = null; + this.isConnected = false; + this.isRtspRunning = false; + this.frameCount = 0; + this.reconnectAttempts = 0; + this.maxReconnectAttempts = 5; + this.reconnectInterval = 3000; + + // 后端服务器配置 + this.BACKEND_URL = 'http://localhost:5000'; // 根据实际情况修改 + // 如果是远程服务器,使用: 'http://192.168.1.173:5000' + } + + /** + * 连接WebSocket服务器 + */ + connect() { + try { + console.log(`正在连接到 ${this.BACKEND_URL}`); + + // 创建Socket.IO连接 + this.socket = io(this.BACKEND_URL, { + transports: ['websocket', 'polling'], // 支持WebSocket和轮询 + timeout: 10000, // 连接超时时间 + forceNew: true, // 强制创建新连接 + autoConnect: true // 自动连接 + }); + + this.setupEventListeners(); + + } catch (error) { + console.error('连接异常:', error); + this.onError(error); + } + } + + /** + * 设置事件监听器 + */ + setupEventListeners() { + // 连接成功事件 + this.socket.on('connect', () => { + this.isConnected = true; + this.reconnectAttempts = 0; + console.log(`WebSocket连接成功!Socket ID: ${this.socket.id}`); + this.onConnect(); + }); + + // 连接失败事件 + this.socket.on('connect_error', (error) => { + this.isConnected = false; + console.error('连接失败:', error.message); + this.onConnectError(error); + this.attemptReconnect(); + }); + + // 断开连接事件 + this.socket.on('disconnect', (reason) => { + this.isConnected = false; + this.isRtspRunning = false; + console.log('连接断开:', reason); + this.onDisconnect(reason); + + // 如果不是主动断开,尝试重连 + if (reason !== 'io client disconnect') { + this.attemptReconnect(); + } + }); + + // 监听RTSP状态事件 + this.socket.on('rtsp_status', (data) => { + console.log('RTSP状态:', data); + this.handleRtspStatus(data); + }); + + // 监听RTSP帧数据 + this.socket.on('rtsp_frame', (data) => { + if (data.image) { + this.frameCount++; + this.onRtspFrame(data.image); + + // 每30帧记录一次 + if (this.frameCount % 30 === 0) { + console.log(`已接收 ${this.frameCount} 帧`); + } + } + }); + } + + /** + * 断开WebSocket连接 + */ + disconnect() { + if (this.socket) { + this.socket.disconnect(); + this.socket = null; + this.isConnected = false; + this.isRtspRunning = false; + console.log('主动断开连接'); + } + } + + /** + * 启动RTSP视频流 + */ + startRtsp() { + if (this.socket && this.isConnected) { + console.log('发送start_rtsp事件'); + this.socket.emit('start_rtsp'); + this.frameCount = 0; + } else { + console.warn('WebSocket未连接,无法启动RTSP'); + } + } + + /** + * 停止RTSP视频流 + */ + stopRtsp() { + if (this.socket && this.isConnected) { + console.log('发送stop_rtsp事件'); + this.socket.emit('stop_rtsp'); + } else { + console.warn('WebSocket未连接,无法停止RTSP'); + } + } + + /** + * 处理RTSP状态变化 + */ + handleRtspStatus(data) { + switch (data.status) { + case 'started': + this.isRtspRunning = true; + this.onRtspStarted(); + break; + case 'stopped': + this.isRtspRunning = false; + this.onRtspStopped(); + break; + case 'already_running': + console.log('RTSP已在运行中'); + this.isRtspRunning = true; + break; + case 'error': + console.error('RTSP错误:', data.message); + this.onRtspError(data.message); + break; + } + } + + /** + * 尝试重连 + */ + attemptReconnect() { + if (this.reconnectAttempts < this.maxReconnectAttempts) { + this.reconnectAttempts++; + console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`); + + setTimeout(() => { + this.connect(); + }, this.reconnectInterval); + } else { + console.error('WebSocket重连失败,已达到最大重试次数'); + this.onReconnectFailed(); + } + } + + // ========== 事件回调函数(可以被重写) ========== + + /** + * 连接成功回调 + */ + onConnect() { + // 可以在这里添加连接成功后的逻辑 + console.log('WebSocket连接成功回调'); + } + + /** + * 连接错误回调 + */ + onConnectError(error) { + // 可以在这里添加连接错误处理逻辑 + console.log('WebSocket连接错误回调:', error); + } + + /** + * 断开连接回调 + */ + onDisconnect(reason) { + // 可以在这里添加断开连接处理逻辑 + console.log('WebSocket断开连接回调:', reason); + } + + /** + * 通用错误回调 + */ + onError(error) { + // 可以在这里添加错误处理逻辑 + console.log('WebSocket错误回调:', error); + } + + /** + * RTSP启动回调 + */ + onRtspStarted() { + console.log('RTSP视频流已启动'); + } + + /** + * RTSP停止回调 + */ + onRtspStopped() { + console.log('RTSP视频流已停止'); + } + + /** + * RTSP错误回调 + */ + onRtspError(message) { + console.error('RTSP错误:', message); + } + + /** + * RTSP帧数据回调 + * @param {string} base64Image - Base64编码的图像数据 + */ + onRtspFrame(base64Image) { + // 在这里处理接收到的视频帧 + // 例如:显示在img元素中 + const imgElement = document.getElementById('rtspImage'); + if (imgElement) { + imgElement.src = 'data:image/jpeg;base64,' + base64Image; + } + } + + /** + * 重连失败回调 + */ + onReconnectFailed() { + console.error('WebSocket重连失败'); + } +} + +// ========== 使用示例 ========== + +// 创建WebSocket管理器实例 +const wsManager = new WebSocketManager(); + +// 重写回调函数(可选) +wsManager.onConnect = function() { + console.log('自定义连接成功处理'); + // 连接成功后可以自动启动RTSP + // this.startRtsp(); +}; + +wsManager.onRtspFrame = function(base64Image) { + // 自定义帧处理逻辑 + const imgElement = document.getElementById('videoDisplay'); + if (imgElement) { + imgElement.src = 'data:image/jpeg;base64,' + base64Image; + imgElement.style.display = 'block'; + } +}; + +// ========== 具体使用方法 ========== + +/** + * 1. 连接WebSocket + */ +function connectWebSocket() { + wsManager.connect(); +} + +/** + * 2. 断开WebSocket + */ +function disconnectWebSocket() { + wsManager.disconnect(); +} + +/** + * 3. 启动RTSP视频流 + */ +function startRtspStream() { + wsManager.startRtsp(); +} + +/** + * 4. 停止RTSP视频流 + */ +function stopRtspStream() { + wsManager.stopRtsp(); +} + +/** + * 5. 检查连接状态 + */ +function checkConnectionStatus() { + console.log('连接状态:', wsManager.isConnected); + console.log('RTSP状态:', wsManager.isRtspRunning); + console.log('接收帧数:', wsManager.frameCount); +} + +// ========== HTML页面中的使用示例 ========== +/* + + + + WebSocket RTSP示例 + + + +
+ + + + + +
+ +
+

视频显示

+ +
+ + + + +*/ + +// ========== Node.js环境中的使用示例 ========== +/* +// 安装依赖: npm install socket.io-client +const { io } = require('socket.io-client'); + +// 然后使用上面的WebSocketManager类 +const wsManager = new WebSocketManager(); +wsManager.connect(); + +// 5秒后启动RTSP +setTimeout(() => { + wsManager.startRtsp(); +}, 5000); + +// 30秒后停止RTSP并断开连接 +setTimeout(() => { + wsManager.stopRtsp(); + setTimeout(() => { + wsManager.disconnect(); + }, 2000); +}, 30000); +*/ + +// 导出类(用于模块化) +if (typeof module !== 'undefined' && module.exports) { + module.exports = WebSocketManager; +} + +// 全局暴露(用于浏览器环境) +if (typeof window !== 'undefined') { + window.WebSocketManager = WebSocketManager; + window.wsManager = wsManager; +} + +console.log('WebSocket管理器已加载,可以使用 wsManager 实例或创建新的 WebSocketManager 实例'); +console.log('使用方法:'); +console.log('1. wsManager.connect() - 连接WebSocket'); +console.log('2. wsManager.startRtsp() - 启动RTSP视频流'); +console.log('3. wsManager.stopRtsp() - 停止RTSP视频流'); +console.log('4. wsManager.disconnect() - 断开WebSocket连接'); \ No newline at end of file diff --git a/start_debug.bat b/start_debug.bat new file mode 100644 index 00000000..07bfd599 --- /dev/null +++ b/start_debug.bat @@ -0,0 +1,100 @@ +@echo off +echo ==================================== +echo Body Balance Evaluation System - Debug Mode +echo ==================================== +echo. + +:: Check Python +python --version >nul 2>&1 +if %errorlevel% neq 0 ( + echo [Error] Python not found, please install Python 3.8 or higher + pause + exit /b 1 +) + +:: Show version info +echo [Info] Checking environment versions... +for /f "tokens=*" %%i in ('python --version') do echo Python: %%i +echo. + +:: Check virtual environment +if not exist "backend\venv" ( + echo [Info] Creating Python virtual environment... + python -m venv backend\venv + if %errorlevel% neq 0 ( + echo [Error] Failed to create virtual environment + pause + exit /b 1 + ) +) + +:: Activate virtual environment +echo [Info] Activating virtual environment... +call backend\venv\Scripts\activate.bat +if %errorlevel% neq 0 ( + echo [Error] Failed to activate virtual environment + pause + exit /b 1 +) + +:: Install Python dependencies +echo [Info] Checking and installing Python dependencies... +if not exist "backend\requirements.txt" ( + echo [Error] requirements.txt file not found + pause + exit /b 1 +) + +pip install -r backend\requirements.txt +if %errorlevel% neq 0 ( + echo [Error] Failed to install Python dependencies + pause + exit /b 1 +) + +:: Create necessary directories +echo [Info] Creating necessary directories... +if not exist "data" mkdir data +if not exist "data\patients" mkdir data\patients +if not exist "data\sessions" mkdir data\sessions +if not exist "data\exports" mkdir data\exports +if not exist "data\backups" mkdir data\backups +if not exist "logs" mkdir logs +if not exist "temp" mkdir temp + +:: Start application in debug mode +echo. +echo ==================================== +echo Starting Debug Mode +echo ==================================== +echo [Info] Starting backend server in debug mode... +echo [Info] Backend address: http://127.0.0.1:5000 +echo [Info] Debug mode enabled - you can set breakpoints in your IDE +echo [Info] Press Ctrl+C to stop service +echo. +echo [Debug Tips]: +echo 1. Open your IDE (VS Code, PyCharm, etc.) +echo 2. Set breakpoints in backend\app.py or other Python files +echo 3. Attach debugger to the running process if needed +echo 4. Use browser dev tools for frontend debugging +echo. + +:: Set environment variables for debugging +set FLASK_ENV=development +set FLASK_DEBUG=1 +set PYTHONPATH=%cd% + +:: Start main program with debug flags +python -u backend\app.py + +if %errorlevel% neq 0 ( + echo. + echo [Error] Application startup failed + echo [Tip] Please check error messages and fix issues + pause + exit /b 1 +) + +echo. +echo [Info] Debug session ended +pause \ No newline at end of file diff --git a/test_websocket.py b/test_websocket.py new file mode 100644 index 00000000..5f88fc9c --- /dev/null +++ b/test_websocket.py @@ -0,0 +1,53 @@ +import socketio +import time + +# 创建SocketIO客户端 +sio = socketio.SimpleClient() + +print('连接WebSocket并监听事件...') + +try: + # 连接到服务器 + print('正在连接到192.168.1.173:5000...') + sio.connect('http://192.168.1.173:5000', wait_timeout=10) + print('WebSocket连接成功!') + + # 发送启动RTSP事件 + sio.emit('start_rtsp') + print('已发送start_rtsp事件,等待5秒接收数据...') + + # 等待并接收事件 + for i in range(5): + try: + # 接收事件 + event = sio.receive(timeout=1) + if event: + event_name, data = event + print(f'收到事件: {event_name}, 数据类型: {type(data)}') + if event_name == 'rtsp_frame' and isinstance(data, dict) and 'image' in data: + print(f'收到图像数据,长度: {len(data["image"])} 字符') + elif event_name == 'rtsp_status': + print(f'RTSP状态: {data}') + except socketio.exceptions.TimeoutError: + print(f'等待事件超时 ({i+1}/5)') + + # 发送停止RTSP事件 + sio.emit('stop_rtsp') + print('已发送stop_rtsp事件') + + # 等待停止状态事件 + try: + event = sio.receive(timeout=2) + if event: + event_name, data = event + print(f'收到停止事件: {event_name}, 数据: {data}') + except socketio.exceptions.TimeoutError: + print('等待停止事件超时') + + sio.disconnect() + print('WebSocket连接已断开') + +except Exception as e: + print(f'测试过程中发生错误: {e}') + +print('WebSocket测试完成') \ No newline at end of file diff --git a/vue_websocket_example.vue b/vue_websocket_example.vue new file mode 100644 index 00000000..eda47041 --- /dev/null +++ b/vue_websocket_example.vue @@ -0,0 +1,421 @@ + + + + + \ No newline at end of file