修正了打包对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/ dist/
build/ build/
# 前端构建输出
frontend/src/renderer/dist/
frontend/src/renderer/dist-electron/
# 临时文件 # 临时文件
*.tmp *.tmp
*.temp *.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/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/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/ob_usb.dll', 'dll/femtobolt/bin'), # Orbbec USB库
('dll/femtobolt/bin/live555.dll', 'dll/femtobolt/bin'), # Live555库 ('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/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=[ hiddenimports=[
'flask', 'flask',

View File

@ -42,7 +42,8 @@ a = Analysis(
('dll/femtobolt/bin/ob_usb.dll', 'dll/femtobolt/bin'), # Orbbec USB库 ('dll/femtobolt/bin/ob_usb.dll', 'dll/femtobolt/bin'), # Orbbec USB库
('dll/femtobolt/bin/live555.dll', 'dll/femtobolt/bin'), # Live555库 ('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/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=[ hiddenimports=[
'flask', 'flask',

View File

@ -11,7 +11,7 @@ import json
import logging import logging
from typing import Dict, Any, Optional, Union from typing import Dict, Any, Optional, Union
from pathlib import Path from pathlib import Path
import sys
class ConfigManager: class ConfigManager:
"""配置管理器""" """配置管理器"""
@ -45,9 +45,15 @@ class ConfigManager:
""" """
# 可能的配置文件路径 # 可能的配置文件路径
possible_paths = [ 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: for path in possible_paths:
abs_path = os.path.abspath(path) abs_path = os.path.abspath(path)
if os.path.exists(abs_path): if os.path.exists(abs_path):

View File

@ -129,6 +129,10 @@ class AppServer:
logging.StreamHandler() logging.StreamHandler()
] ]
) )
# 设置werkzeug日志级别为WARNING过滤掉INFO级别的访问日志
logging.getLogger('werkzeug').setLevel(logging.WARNING)
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
def _init_socketio(self): def _init_socketio(self):
@ -143,10 +147,10 @@ class AppServer:
engineio_logger=False, engineio_logger=False,
ping_timeout=60, ping_timeout=60,
ping_interval=25, ping_interval=25,
manage_session=True, # 启用会话管理,解决打包环境会话问题 manage_session=False,
always_connect=False, always_connect=False,
transports=['polling'], # 只使用polling避免打包环境websocket问题 transports=['polling', 'websocket'], # 优先使用polling
allow_upgrades=False, # 禁用升级到websocket allow_upgrades=True, # 允许升级到websocket
cookie=None # 禁用cookie cookie=None # 禁用cookie
) )
self.logger.info('SocketIO初始化成功') 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
socket = io(BACKEND_URL, { socket = io(BACKEND_URL, {
transports: ['polling'], // 使polling transports: ['websocket', 'polling'], // 使polling
timeout: 10000, timeout: 10000,
forceNew: true, forceNew: true,
reconnection: true, reconnection: true,
@ -844,7 +844,7 @@ function connectWebSocket() {
// //
devicesSocket = io(BACKEND_URL + '/devices', { devicesSocket = io(BACKEND_URL + '/devices', {
transports: ['polling'], // 使polling transports: ['websocket', 'polling'], // 使polling
timeout: 10000, timeout: 10000,
forceNew: true forceNew: true
}) })
@ -2722,7 +2722,11 @@ onUnmounted(() => {
} }
:deep(.el-form-item__label) { :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) { :deep(.el-form-item__label) {
font-weight: 500; font-size: 14px !important;
color: #606266; font-family: '苹方 粗体', '苹方 中等', '苹方', sans-serif !important;
font-weight: 700 !important;
font-style: normal !important;
color: #FFFFFF !important;
} }
:deep(.el-form-item__content) { :deep(.el-form-item__content) {