修正了打包对socket模式的支持

This commit is contained in:
root 2025-08-19 08:30:48 +08:00 committed by zhaozilong12
parent cb64dd52b6
commit 7d13b777ce
12 changed files with 221 additions and 50 deletions

19
.gitignore vendored
View File

@ -43,6 +43,10 @@ Thumbs.db
dist/
build/
# 前端构建输出
frontend/src/renderer/dist/
frontend/src/renderer/dist-electron/
# 临时文件
*.tmp
*.temp
@ -21394,3 +21398,18 @@ frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBa
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/_internal/werkzeug-2.3.7.dist-info/WHEEL
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/Log/OrbbecSDK.log.txt
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/Log/OrbbecSDK.log.txt
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/config.ini
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/depthengine_2_0.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/k4a.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/k4arecord.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/live555.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/ob_usb.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/OrbbecSDK.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/bin/OrbbecSDKConfig_v1.0.xml
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/lib/k4a.lib
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/femtobolt/lib/k4arecord.lib
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/smitsense/SMiTSenseUsb-F3.0.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/smitsense/SMiTSenseUsb-F3.0.lib
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/smitsense/SMiTSenseUsb-F3.0d.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/smitsense/SMiTSenseUsbWrapper.dll
frontend/src/renderer/dist-electron/win-unpacked/resources/backend/BodyBalanceBackend/dll/smitsense/Wrapper.dll

View File

@ -14,7 +14,8 @@ a = Analysis(
('dll/femtobolt/bin/ob_usb.dll', 'dll/femtobolt/bin'), # Orbbec USB库
('dll/femtobolt/bin/live555.dll', 'dll/femtobolt/bin'), # Live555库
('dll/femtobolt/bin/OrbbecSDKConfig_v1.0.xml', 'dll/femtobolt/bin'), # Orbbec配置文件 ('dll/smitsense/SMiTSenseUsb-F3.0.dll', 'dll/smitsense'), # SMiTSense传感器库
('dll/smitsense/SMiTSenseUsbWrapper.dll', 'dll/smitsense'), # SMiTSense传感器库包装类
('dll/smitsense/Wrapper.dll', 'dll/smitsense'), # Wrapper
('dll/smitsense/SMiTSenseUsb-F3.0.dll', 'dll/smitsense'), # Wrapper
],
hiddenimports=[
'flask',

View File

@ -42,7 +42,8 @@ a = Analysis(
('dll/femtobolt/bin/ob_usb.dll', 'dll/femtobolt/bin'), # Orbbec USB库
('dll/femtobolt/bin/live555.dll', 'dll/femtobolt/bin'), # Live555库
('dll/femtobolt/bin/OrbbecSDKConfig_v1.0.xml', 'dll/femtobolt/bin'), # Orbbec配置文件 ('dll/smitsense/SMiTSenseUsb-F3.0.dll', 'dll/smitsense'), # SMiTSense传感器库
('dll/smitsense/SMiTSenseUsbWrapper.dll', 'dll/smitsense'), # SMiTSense传感器库包装类
('dll/smitsense/Wrapper.dll', 'dll/smitsense'), # Wrapper
('dll/smitsense/SMiTSenseUsb-F3.0.dll', 'dll/smitsense'), # Wrapper
],
hiddenimports=[
'flask',

View File

@ -11,7 +11,7 @@ import json
import logging
from typing import Dict, Any, Optional, Union
from pathlib import Path
import sys
class ConfigManager:
"""配置管理器"""
@ -45,9 +45,15 @@ class ConfigManager:
"""
# 可能的配置文件路径
possible_paths = [
os.path.join(os.path.dirname(__file__), 'config.ini')
# os.path.join(os.path.dirname(__file__), 'config.ini')
]
# 配置文件路径
if getattr(sys, 'frozen', False):
# 打包后的可执行文件
possible_paths.append(os.path.join(os.path.dirname(sys.executable), 'config.ini'))
else:
# 开发环境
possible_paths.append(os.path.join(os.path.dirname(__file__), 'config.ini'))
for path in possible_paths:
abs_path = os.path.abspath(path)
if os.path.exists(abs_path):

View File

@ -129,6 +129,10 @@ class AppServer:
logging.StreamHandler()
]
)
# 设置werkzeug日志级别为WARNING过滤掉INFO级别的访问日志
logging.getLogger('werkzeug').setLevel(logging.WARNING)
self.logger = logging.getLogger(__name__)
def _init_socketio(self):
@ -143,10 +147,10 @@ class AppServer:
engineio_logger=False,
ping_timeout=60,
ping_interval=25,
manage_session=True, # 启用会话管理,解决打包环境会话问题
manage_session=False,
always_connect=False,
transports=['polling'], # 只使用polling避免打包环境websocket问题
allow_upgrades=False, # 禁用升级到websocket
transports=['polling', 'websocket'], # 优先使用polling
allow_upgrades=True, # 允许升级到websocket
cookie=None # 禁用cookie
)
self.logger.info('SocketIO初始化成功')

View File

@ -0,0 +1,66 @@
import psutil
import time
from datetime import datetime
from pynvml import *
def get_memory_usage():
mem = psutil.virtual_memory()
return mem.percent, mem.used / (1024 ** 3), mem.total / (1024 ** 3)
def get_cpu_usage():
return psutil.cpu_percent(interval=1) # 获取CPU利用率百分比
def get_gpu_usage():
try:
nvmlInit()
device_count = nvmlDeviceGetCount()
gpu_stats = []
for i in range(device_count):
handle = nvmlDeviceGetHandleByIndex(i)
name = nvmlDeviceGetName(handle).decode("utf-8")
mem_info = nvmlDeviceGetMemoryInfo(handle)
util = nvmlDeviceGetUtilizationRates(handle)
gpu_stats.append({
"name": name,
"gpu_util": util.gpu,
"mem_util": util.memory,
"mem_used": mem_info.used / (1024 ** 3),
"mem_total": mem_info.total / (1024 ** 3)
})
nvmlShutdown()
return gpu_stats
except Exception:
return [{"name": "N/A", "gpu_util": 0, "mem_util": 0, "mem_used": 0, "mem_total": 0}]
def main():
log_file = "monitor_log.txt"
with open(log_file, "a", encoding="utf-8") as f:
while True:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# CPU
cpu_percent = get_cpu_usage()
# 内存
mem_percent, mem_used, mem_total = get_memory_usage()
# GPU
gpu_stats = get_gpu_usage()
# 拼接日志内容
log_line = (f"[{now}] CPU: {cpu_percent:.1f}% | "
f"Memory: {mem_percent:.1f}% ({mem_used:.2f} GB / {mem_total:.2f} GB)")
for gpu in gpu_stats:
log_line += (f" | GPU: {gpu['name']} {gpu['gpu_util']}% "
f"(Mem {gpu['mem_used']:.2f} GB / {gpu['mem_total']:.2f} GB)")
# 输出
print(log_line)
f.write(log_line + "\n")
f.flush()
time.sleep(9) # 这里+CPU统计的1秒总体大约10秒一个周期
if __name__ == "__main__":
main()

View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
class FemtoBoltViewer:
def __init__(self, depth_min=900, depth_max=1300):
self.depth_min = depth_min
self.depth_max = depth_max
# 自定义colormap
colors = ['fuchsia', 'red', 'yellow', 'lime', 'cyan', 'blue',
'fuchsia', 'red', 'yellow', 'lime', 'cyan', 'blue']
self.cmap = LinearSegmentedColormap.from_list("custom_cmap", colors)
# SDK设备句柄
self.device_handle = None
self.pykinect = None
self.config = None
# 初始化matplotlib figure
plt.ion()
self.fig, self.ax = plt.subplots(figsize=(7, 7))
def _load_sdk(self):
"""加载FemtoBolt SDK"""
try:
import pykinect_azure as pykinect
self.pykinect = pykinect
# 配置DLL路径
base_dir = os.path.dirname(os.path.abspath(__file__))
dll_path = os.path.join(base_dir, "..", "dll", "femtobolt", "bin", "k4a.dll")
self.pykinect.initialize_libraries(track_body=False, module_k4a_path=dll_path)
return True
except Exception as e:
print(f"加载SDK失败: {e}")
return False
def _configure_device(self):
"""配置FemtoBolt设备"""
self.config = self.pykinect.default_configuration
self.config.depth_mode = self.pykinect.K4A_DEPTH_MODE_NFOV_UNBINNED
self.config.camera_fps = self.pykinect.K4A_FRAMES_PER_SECOND_15
self.config.synchronized_images_only = False
self.config.color_resolution = 0
self.device_handle = self.pykinect.start_device(config=self.config)
def _render_depth(self, depth_image: np.ndarray):
"""使用matplotlib绘制深度图带背景和自定义colormap"""
# 过滤深度范围
depth = np.where((depth_image >= self.depth_min) & (depth_image <= self.depth_max),
depth_image, 0)
# 屏蔽深度为0的部分
depth = np.ma.masked_equal(depth, 0)
# 背景图(灰色)
background = np.ones_like(depth) * 0.5
self.ax.clear()
# 绘制背景
self.ax.imshow(background, origin='lower', cmap='gray', alpha=0.3)
# 绘制白色栅格线
self.ax.grid(True, which='both', axis='both', color='white', linestyle='-', linewidth=1, zorder=0)
# 绘制深度等高线
self.ax.contourf(depth, levels=200, cmap=self.cmap, vmin=self.depth_min, vmax=self.depth_max, origin='upper', zorder=2)
plt.pause(0.001)
plt.draw()
def run(self):
if not self._load_sdk():
print("SDK加载失败退出")
return
self._configure_device()
print("FemtoBolt深度相机启动成功按 Ctrl+C 退出")
try:
while True:
capture = self.device_handle.update()
if capture is None:
continue
ret, depth_image = capture.get_depth_image()
if not ret or depth_image is None:
continue
self._render_depth(depth_image)
except KeyboardInterrupt:
print("退出程序")
finally:
self.device_handle.stop()
self.device_handle.close()
plt.close(self.fig)
if __name__ == "__main__":
viewer = FemtoBoltViewer(depth_min=900, depth_max=1300)
viewer.run()

View File

@ -1,20 +0,0 @@
[08/15 15:17:24.789452][debug][11108][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\frontend\src\renderer\dist-electron\win-unpacked\resources\backend
[08/15 15:17:24.789708][debug][11108][Context.cpp:49] Config file version=1.1
[08/15 15:17:24.789777][debug][11108][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
[08/15 15:17:24.789813][info][11108][Context.cpp:68] Context created with config: default config!
[08/15 15:17:24.789902][info][11108][Context.cpp:73] Work directory=D:\Trae_space\BodyBalanceEvaluation\frontend\src\renderer\dist-electron\win-unpacked\resources\backend, SDK version=v1.10.11-20240724-aeaa107e5
[08/15 15:17:24.790186][debug][11108][DeviceManager.cpp:30] DeviceManager init ...
[08/15 15:17:24.790207][info][11108][MfPal.cpp:105] createObPal: create WinPal!
[08/15 15:17:24.790229][debug][11108][MfPal.cpp:110] WmfPal init ...
[08/15 15:17:24.816565][debug][11108][MfPal.cpp:117] WmfPal created!
[08/15 15:17:24.816602][debug][11108][DeviceManager.cpp:34] Enable USB Device Enumerator ...
[08/15 15:17:24.842574][debug][11108][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
[08/15 15:17:24.842902][debug][11108][MfPal.cpp:216] Create WinEventDeviceWatcher!
[08/15 15:17:24.843143][debug][11108][UsbDeviceEnumerator.cpp:78] No matched usb device found!
[08/15 15:17:24.843178][info][11108][DeviceManager.cpp:15] Current found device(s): (0)
[08/15 15:17:24.843199][debug][11108][DeviceManager.cpp:52] DeviceManager construct done!
[08/15 15:17:24.843226][debug][11108][Context.cpp:81] Context destroying ...
[08/15 15:17:24.843236][debug][11108][DeviceManager.cpp:56] DeviceManager destroy ...
[08/15 15:17:24.843245][debug][11108][DeviceManager.cpp:64] DeviceManager Destructors done
[08/15 15:17:24.983361][debug][11108][MfPal.cpp:128] WmfPal destroyed!
[08/15 15:17:24.984152][info][11108][Context.cpp:84] Context destroyed

View File

@ -1,17 +0,0 @@
@echo off
echo 启动身体平衡评估系统后端服务(完整版)...
echo.
echo 服务信息:
echo - HTTP API: http://localhost:5000
echo - SocketIO: ws://localhost:5000
echo - 管理界面: http://localhost:5000
echo.
echo 按Ctrl+C停止服务
echo.
cd BodyBalanceBackend
"BodyBalanceBackend.exe"
if %errorlevel% neq 0 (
echo.
echo 服务启动失败,请检查错误信息
pause
)

View File

@ -834,7 +834,7 @@ function connectWebSocket() {
// Socket.IO
socket = io(BACKEND_URL, {
transports: ['polling'], // 使polling
transports: ['websocket', 'polling'], // 使polling
timeout: 10000,
forceNew: true,
reconnection: true,
@ -844,7 +844,7 @@ function connectWebSocket() {
//
devicesSocket = io(BACKEND_URL + '/devices', {
transports: ['polling'], // 使polling
transports: ['websocket', 'polling'], // 使polling
timeout: 10000,
forceNew: true
})
@ -2722,7 +2722,11 @@ onUnmounted(() => {
}
:deep(.el-form-item__label) {
color: #ffffff;
color: #ffffff !important;
font-size: 14px !important;
font-family: '苹方 粗体', '苹方 中等', '苹方', sans-serif !important;
font-weight: 700 !important;
font-style: normal !important;
}

View File

@ -433,8 +433,11 @@ const handleSaveAndDetect = async () => {
}
:deep(.el-form-item__label) {
font-weight: 500;
color: #606266;
font-size: 14px !important;
font-family: '苹方 粗体', '苹方 中等', '苹方', sans-serif !important;
font-weight: 700 !important;
font-style: normal !important;
color: #FFFFFF !important;
}
:deep(.el-form-item__content) {