Merge branch 'main' of http://121.37.111.42:3000/ThbTech/BodyBalanceEvaluation
This commit is contained in:
commit
d39a2c7695
4
.gitignore
vendored
4
.gitignore
vendored
@ -43,6 +43,10 @@ Thumbs.db
|
||||
dist/
|
||||
build/
|
||||
|
||||
# 前端构建输出
|
||||
frontend/src/renderer/dist/
|
||||
frontend/src/renderer/dist-electron/
|
||||
|
||||
# 临时文件
|
||||
*.tmp
|
||||
*.temp
|
||||
|
@ -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',
|
||||
|
@ -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/SMiTSenseUsb-F3.0.dll', 'dll/smitsense'), # SMiTSenseUsb库
|
||||
('dll/smitsense/Wrapper.dll', 'dll/smitsense'), # SMiTSense传感器库包装类
|
||||
],
|
||||
hiddenimports=[
|
||||
'flask',
|
||||
|
@ -29,7 +29,7 @@ depth_range_max = 1700
|
||||
|
||||
[DEVICES]
|
||||
imu_device_type = real
|
||||
imu_port = COM3
|
||||
imu_port = COM7
|
||||
imu_baudrate = 9600
|
||||
pressure_device_type = real
|
||||
pressure_use_mock = False
|
||||
|
@ -11,7 +11,7 @@ import json
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, Union
|
||||
from pathlib import Path
|
||||
|
||||
import sys
|
||||
|
||||
class ConfigManager:
|
||||
"""配置管理器"""
|
||||
@ -43,10 +43,23 @@ class ConfigManager:
|
||||
Returns:
|
||||
str: 配置文件路径
|
||||
"""
|
||||
import sys
|
||||
|
||||
# 可能的配置文件路径
|
||||
possible_paths = [
|
||||
os.path.join(os.path.dirname(__file__), 'config.ini')
|
||||
]
|
||||
possible_paths = []
|
||||
|
||||
# 如果是打包后的exe文件,从exe文件同级目录获取
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的exe文件路径
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
possible_paths.append(os.path.join(exe_dir, 'config.ini'))
|
||||
|
||||
# 开发环境下的路径
|
||||
possible_paths.extend([
|
||||
os.path.join(os.path.dirname(__file__), 'config.ini'),
|
||||
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'config.ini'), # backend/config.ini
|
||||
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'config.ini') # 项目根目录/config.ini
|
||||
])
|
||||
|
||||
for path in possible_paths:
|
||||
abs_path = os.path.abspath(path)
|
||||
@ -54,8 +67,14 @@ class ConfigManager:
|
||||
self.logger.info(f"找到配置文件: {abs_path}")
|
||||
return abs_path
|
||||
|
||||
# 如果都找不到,返回默认路径(exe同级目录或backend目录)
|
||||
if getattr(sys, 'frozen', False):
|
||||
default_path = os.path.join(os.path.dirname(sys.executable), 'config.ini')
|
||||
else:
|
||||
default_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'config.ini')
|
||||
|
||||
|
||||
self.logger.warning(f"未找到配置文件,使用默认路径: {default_path}")
|
||||
return default_path
|
||||
def _load_config(self):
|
||||
"""
|
||||
加载配置文件
|
||||
|
Binary file not shown.
@ -147,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初始化成功')
|
||||
@ -205,9 +205,9 @@ class AppServer:
|
||||
self.logger.info('正在初始化设备管理器...')
|
||||
self.device_managers = {
|
||||
'camera': CameraManager(self.socketio, self.config_manager),
|
||||
'femtobolt': FemtoBoltManager(self.socketio, self.config_manager),
|
||||
'imu': IMUManager(self.socketio, self.config_manager),
|
||||
'pressure': PressureManager(self.socketio, self.config_manager)
|
||||
# 'femtobolt': FemtoBoltManager(self.socketio, self.config_manager),
|
||||
# 'imu': IMUManager(self.socketio, self.config_manager),
|
||||
# 'pressure': PressureManager(self.socketio, self.config_manager)
|
||||
}
|
||||
|
||||
# 为每个设备添加状态变化回调
|
||||
|
66
backend/tests/moniter_windows.py
Normal file
66
backend/tests/moniter_windows.py
Normal 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()
|
104
backend/tests/testfemtobolt.py
Normal file
104
backend/tests/testfemtobolt.py
Normal 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()
|
@ -1,40 +0,0 @@
|
||||
[08/18 20:41:43.488456][debug][24904][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\frontend\src\renderer\dist-electron\win-unpacked\resources\backend
|
||||
[08/18 20:41:43.488655][debug][24904][Context.cpp:49] Config file version=1.1
|
||||
[08/18 20:41:43.488739][debug][24904][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
||||
[08/18 20:41:43.488782][info][24904][Context.cpp:68] Context created with config: default config!
|
||||
[08/18 20:41:43.488823][info][24904][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/18 20:41:43.489074][debug][24904][DeviceManager.cpp:30] DeviceManager init ...
|
||||
[08/18 20:41:43.489100][info][24904][MfPal.cpp:105] createObPal: create WinPal!
|
||||
[08/18 20:41:43.489124][debug][24904][MfPal.cpp:110] WmfPal init ...
|
||||
[08/18 20:41:43.520661][debug][24904][MfPal.cpp:117] WmfPal created!
|
||||
[08/18 20:41:43.520721][debug][24904][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
||||
[08/18 20:41:43.553521][debug][24904][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
||||
[08/18 20:41:43.553940][debug][24904][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
||||
[08/18 20:41:43.554220][debug][24904][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
||||
[08/18 20:41:43.554276][info][24904][DeviceManager.cpp:15] Current found device(s): (0)
|
||||
[08/18 20:41:43.554305][debug][24904][DeviceManager.cpp:52] DeviceManager construct done!
|
||||
[08/18 20:41:43.554347][debug][24904][Context.cpp:81] Context destroying ...
|
||||
[08/18 20:41:43.554360][debug][24904][DeviceManager.cpp:56] DeviceManager destroy ...
|
||||
[08/18 20:41:43.554371][debug][24904][DeviceManager.cpp:64] DeviceManager Destructors done
|
||||
[08/18 20:41:43.558317][debug][24904][MfPal.cpp:128] WmfPal destroyed!
|
||||
[08/18 20:41:43.558735][info][24904][Context.cpp:84] Context destroyed
|
||||
[08/18 20:43:03.299275][debug][29780][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\frontend\src\renderer\dist-electron\win-unpacked\resources\backend
|
||||
[08/18 20:43:03.299338][debug][29780][Context.cpp:49] Config file version=1.1
|
||||
[08/18 20:43:03.299358][debug][29780][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
||||
[08/18 20:43:03.299375][info][29780][Context.cpp:68] Context created with config: default config!
|
||||
[08/18 20:43:03.299399][info][29780][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/18 20:43:03.299416][debug][29780][DeviceManager.cpp:30] DeviceManager init ...
|
||||
[08/18 20:43:03.299428][info][29780][MfPal.cpp:105] createObPal: create WinPal!
|
||||
[08/18 20:43:03.299441][debug][29780][MfPal.cpp:110] WmfPal init ...
|
||||
[08/18 20:43:03.340690][debug][29780][MfPal.cpp:117] WmfPal created!
|
||||
[08/18 20:43:03.340727][debug][29780][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
||||
[08/18 20:43:03.367003][debug][29780][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
||||
[08/18 20:43:03.367322][debug][29780][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
||||
[08/18 20:43:03.367577][debug][29780][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
||||
[08/18 20:43:03.367605][info][29780][DeviceManager.cpp:15] Current found device(s): (0)
|
||||
[08/18 20:43:03.367629][debug][29780][DeviceManager.cpp:52] DeviceManager construct done!
|
||||
[08/18 20:43:03.367646][debug][29780][Context.cpp:81] Context destroying ...
|
||||
[08/18 20:43:03.367657][debug][29780][DeviceManager.cpp:56] DeviceManager destroy ...
|
||||
[08/18 20:43:03.367667][debug][29780][DeviceManager.cpp:64] DeviceManager Destructors done
|
||||
[08/18 20:43:03.369012][debug][29780][MfPal.cpp:128] WmfPal destroyed!
|
||||
[08/18 20:43:03.369386][info][29780][Context.cpp:84] Context destroyed
|
@ -927,7 +927,7 @@ function connectWebSocket() {
|
||||
|
||||
// 创建主Socket.IO连接
|
||||
socket = io(BACKEND_URL, {
|
||||
transports: ['polling'], // 只使用polling,与后端保持一致
|
||||
transports: ['websocket', 'polling'], // 只使用polling,与后端保持一致
|
||||
timeout: 10000,
|
||||
forceNew: true,
|
||||
reconnection: true,
|
||||
@ -937,7 +937,7 @@ function connectWebSocket() {
|
||||
|
||||
// 创建统一设备命名空间连接
|
||||
devicesSocket = io(BACKEND_URL + '/devices', {
|
||||
transports: ['polling'], // 只使用polling,与后端保持一致
|
||||
transports: ['websocket', 'polling'], // 只使用polling,与后端保持一致
|
||||
timeout: 10000,
|
||||
forceNew: true
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user