提交变动修改
This commit is contained in:
parent
7a768c1701
commit
5b6e0697d2
1277
.gitignore
vendored
1277
.gitignore
vendored
File diff suppressed because it is too large
Load Diff
@ -82,10 +82,8 @@ pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|||||||
exe = EXE(
|
exe = EXE(
|
||||||
pyz,
|
pyz,
|
||||||
a.scripts,
|
a.scripts,
|
||||||
a.binaries,
|
|
||||||
a.zipfiles,
|
|
||||||
a.datas,
|
|
||||||
[],
|
[],
|
||||||
|
exclude_binaries=True,
|
||||||
name='BodyBalanceBackend',
|
name='BodyBalanceBackend',
|
||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
@ -101,3 +99,14 @@ exe = EXE(
|
|||||||
entitlements_file=None,
|
entitlements_file=None,
|
||||||
icon=None
|
icon=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
coll = COLLECT(
|
||||||
|
exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
name='BodyBalanceBackend'
|
||||||
|
)
|
||||||
|
@ -110,10 +110,8 @@ pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|||||||
exe = EXE(
|
exe = EXE(
|
||||||
pyz,
|
pyz,
|
||||||
a.scripts,
|
a.scripts,
|
||||||
a.binaries,
|
|
||||||
a.zipfiles,
|
|
||||||
a.datas,
|
|
||||||
[],
|
[],
|
||||||
|
exclude_binaries=True,
|
||||||
name='BodyBalanceBackend',
|
name='BodyBalanceBackend',
|
||||||
debug=False,
|
debug=False,
|
||||||
bootloader_ignore_signals=False,
|
bootloader_ignore_signals=False,
|
||||||
@ -129,6 +127,17 @@ exe = EXE(
|
|||||||
entitlements_file=None,
|
entitlements_file=None,
|
||||||
icon=None
|
icon=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
coll = COLLECT(
|
||||||
|
exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
name='BodyBalanceBackend'
|
||||||
|
)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
with open('app.spec', 'w', encoding='utf-8') as f:
|
with open('app.spec', 'w', encoding='utf-8') as f:
|
||||||
@ -172,6 +181,7 @@ echo - 管理界面: http://localhost:5000
|
|||||||
echo.
|
echo.
|
||||||
echo 按Ctrl+C停止服务
|
echo 按Ctrl+C停止服务
|
||||||
echo.
|
echo.
|
||||||
|
cd BodyBalanceBackend
|
||||||
"BodyBalanceBackend.exe"
|
"BodyBalanceBackend.exe"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
echo.
|
echo.
|
||||||
@ -240,23 +250,34 @@ def copy_dll_files():
|
|||||||
print(f"⚠️ 复制dll目录内容失败: {e}")
|
print(f"⚠️ 复制dll目录内容失败: {e}")
|
||||||
|
|
||||||
def copy_data_files():
|
def copy_data_files():
|
||||||
"""复制数据库文件到data目录"""
|
"""准备数据库文件到data目录"""
|
||||||
print("复制数据库文件...")
|
print("准备数据库文件...")
|
||||||
|
|
||||||
data_dir = os.path.join('dist', 'data')
|
data_dir = os.path.join('dist', 'data')
|
||||||
|
|
||||||
# 数据库文件列表
|
# 数据库文件列表 - 这些文件会在程序首次运行时自动创建
|
||||||
db_files = ['body_balance.db', 'database.db']
|
db_files = ['body_balance.db', 'database.db']
|
||||||
|
|
||||||
|
# 检查是否存在现有数据库文件,如果存在则复制
|
||||||
|
copied_count = 0
|
||||||
for db_file in db_files:
|
for db_file in db_files:
|
||||||
if os.path.exists(db_file):
|
# 检查当前目录和data目录中的数据库文件
|
||||||
|
source_paths = [db_file, os.path.join('data', db_file)]
|
||||||
|
|
||||||
|
for source_path in source_paths:
|
||||||
|
if os.path.exists(source_path):
|
||||||
try:
|
try:
|
||||||
shutil.copy2(db_file, data_dir)
|
shutil.copy2(source_path, data_dir)
|
||||||
print(f"✓ 已复制 {db_file}")
|
print(f"✓ 已复制 {source_path} -> {data_dir}")
|
||||||
|
copied_count += 1
|
||||||
|
break # 找到一个就跳出内层循环
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 复制 {db_file} 失败: {e}")
|
print(f"⚠️ 复制 {source_path} 失败: {e}")
|
||||||
|
|
||||||
|
if copied_count == 0:
|
||||||
|
print("ℹ️ 未找到现有数据库文件,程序首次运行时将自动创建")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ 数据库文件不存在: {db_file}")
|
print(f"✓ 成功复制 {copied_count} 个数据库文件")
|
||||||
|
|
||||||
def copy_config_files():
|
def copy_config_files():
|
||||||
"""复制配置文件到dist目录"""
|
"""复制配置文件到dist目录"""
|
||||||
@ -308,7 +329,7 @@ def main():
|
|||||||
print("后处理...")
|
print("后处理...")
|
||||||
|
|
||||||
# 检查生成的exe文件
|
# 检查生成的exe文件
|
||||||
exe_path = 'dist/BodyBalanceBackend.exe'
|
exe_path = 'dist/BodyBalanceBackend/BodyBalanceBackend.exe'
|
||||||
if os.path.exists(exe_path):
|
if os.path.exists(exe_path):
|
||||||
print(f"✓ exe文件位置: {exe_path}")
|
print(f"✓ exe文件位置: {exe_path}")
|
||||||
|
|
||||||
@ -340,12 +361,13 @@ def main():
|
|||||||
print("- 配置文件: dist/config.ini")
|
print("- 配置文件: dist/config.ini")
|
||||||
print()
|
print()
|
||||||
print("目录结构:")
|
print("目录结构:")
|
||||||
|
print("- BodyBalanceBackend/ - 应用程序文件夹")
|
||||||
print("- dll/ - DLL文件")
|
print("- dll/ - DLL文件")
|
||||||
print("- data/ - 数据库文件")
|
print("- data/ - 数据库文件")
|
||||||
print("- logs/ - 日志文件")
|
print("- logs/ - 日志文件")
|
||||||
print()
|
print()
|
||||||
print("使用方式:")
|
print("使用方式:")
|
||||||
print("1. 直接运行: dist/BodyBalanceBackend.exe")
|
print("1. 直接运行: dist/BodyBalanceBackend/BodyBalanceBackend.exe")
|
||||||
print("2. 使用脚本: dist/start_backend.bat")
|
print("2. 使用脚本: dist/start_backend.bat")
|
||||||
print()
|
print()
|
||||||
print("服务地址: http://localhost:5000")
|
print("服务地址: http://localhost:5000")
|
||||||
|
@ -12,7 +12,7 @@ class FPMS_DEVICE_C(ctypes.Structure):
|
|||||||
]
|
]
|
||||||
|
|
||||||
class SMiTSenseSensor:
|
class SMiTSenseSensor:
|
||||||
def __init__(self, dll_path = r"D:\BodyBalanceEvaluation\backend\tests\SMiTSenseUsb-F3.0.dll"):
|
def __init__(self, dll_path = r"D:\Trae_space\BodyBalanceEvaluation\backend\tests\SMiTSenseUsbWrapper.dll"):
|
||||||
self.dll = ctypes.WinDLL(dll_path)
|
self.dll = ctypes.WinDLL(dll_path)
|
||||||
|
|
||||||
# 定义函数接口
|
# 定义函数接口
|
||||||
|
@ -4,7 +4,7 @@ import numpy as np
|
|||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
# === DLL 加载 ===
|
# === DLL 加载 ===
|
||||||
dll = ctypes.WinDLL(r"D:\BodyBalanceEvaluation\backend\tests\SMiTSenseUsbWrapper.dll")
|
dll = ctypes.WinDLL(r"D:\Trae_space\BodyBalanceEvaluation\backend\tests\SMiTSenseUsbWrapper.dll")
|
||||||
|
|
||||||
dll.SMiTSenseUsb_Init.argtypes = [ctypes.c_int]
|
dll.SMiTSenseUsb_Init.argtypes = [ctypes.c_int]
|
||||||
dll.SMiTSenseUsb_Init.restype = ctypes.c_int
|
dll.SMiTSenseUsb_Init.restype = ctypes.c_int
|
||||||
|
@ -1,60 +1,20 @@
|
|||||||
[08/15 11:08:00.007828][debug][1996][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\backend\dist
|
[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 11:08:00.007990][debug][1996][Context.cpp:49] Config file version=1.1
|
[08/15 15:17:24.789708][debug][11108][Context.cpp:49] Config file version=1.1
|
||||||
[08/15 11:08:00.008057][debug][1996][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
[08/15 15:17:24.789777][debug][11108][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
||||||
[08/15 11:08:00.008095][info][1996][Context.cpp:68] Context created with config: default config!
|
[08/15 15:17:24.789813][info][11108][Context.cpp:68] Context created with config: default config!
|
||||||
[08/15 11:08:00.008265][info][1996][Context.cpp:73] Work directory=D:\Trae_space\BodyBalanceEvaluation\backend\dist, SDK version=v1.10.11-20240724-aeaa107e5
|
[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 11:08:00.008455][debug][1996][DeviceManager.cpp:30] DeviceManager init ...
|
[08/15 15:17:24.790186][debug][11108][DeviceManager.cpp:30] DeviceManager init ...
|
||||||
[08/15 11:08:00.008674][info][1996][MfPal.cpp:105] createObPal: create WinPal!
|
[08/15 15:17:24.790207][info][11108][MfPal.cpp:105] createObPal: create WinPal!
|
||||||
[08/15 11:08:00.008795][debug][1996][MfPal.cpp:110] WmfPal init ...
|
[08/15 15:17:24.790229][debug][11108][MfPal.cpp:110] WmfPal init ...
|
||||||
[08/15 11:08:00.039058][debug][1996][MfPal.cpp:117] WmfPal created!
|
[08/15 15:17:24.816565][debug][11108][MfPal.cpp:117] WmfPal created!
|
||||||
[08/15 11:08:00.039105][debug][1996][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
[08/15 15:17:24.816602][debug][11108][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
||||||
[08/15 11:08:00.066384][debug][1996][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
[08/15 15:17:24.842574][debug][11108][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
||||||
[08/15 11:08:00.066623][debug][1996][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
[08/15 15:17:24.842902][debug][11108][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
||||||
[08/15 11:08:00.066791][debug][1996][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
[08/15 15:17:24.843143][debug][11108][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
||||||
[08/15 11:08:00.066833][info][1996][DeviceManager.cpp:15] Current found device(s): (0)
|
[08/15 15:17:24.843178][info][11108][DeviceManager.cpp:15] Current found device(s): (0)
|
||||||
[08/15 11:08:00.066975][debug][1996][DeviceManager.cpp:52] DeviceManager construct done!
|
[08/15 15:17:24.843199][debug][11108][DeviceManager.cpp:52] DeviceManager construct done!
|
||||||
[08/15 11:08:00.067012][debug][1996][Context.cpp:81] Context destroying ...
|
[08/15 15:17:24.843226][debug][11108][Context.cpp:81] Context destroying ...
|
||||||
[08/15 11:08:00.067024][debug][1996][DeviceManager.cpp:56] DeviceManager destroy ...
|
[08/15 15:17:24.843236][debug][11108][DeviceManager.cpp:56] DeviceManager destroy ...
|
||||||
[08/15 11:08:00.067033][debug][1996][DeviceManager.cpp:64] DeviceManager Destructors done
|
[08/15 15:17:24.843245][debug][11108][DeviceManager.cpp:64] DeviceManager Destructors done
|
||||||
[08/15 11:08:00.214042][debug][1996][MfPal.cpp:128] WmfPal destroyed!
|
[08/15 15:17:24.983361][debug][11108][MfPal.cpp:128] WmfPal destroyed!
|
||||||
[08/15 11:08:00.214700][info][1996][Context.cpp:84] Context destroyed
|
[08/15 15:17:24.984152][info][11108][Context.cpp:84] Context destroyed
|
||||||
[08/15 11:11:00.761881][debug][12088][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\backend\dist
|
|
||||||
[08/15 11:11:00.762009][debug][12088][Context.cpp:49] Config file version=1.1
|
|
||||||
[08/15 11:11:00.762057][debug][12088][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
|
||||||
[08/15 11:11:00.762081][info][12088][Context.cpp:68] Context created with config: default config!
|
|
||||||
[08/15 11:11:00.762166][info][12088][Context.cpp:73] Work directory=D:\Trae_space\BodyBalanceEvaluation\backend\dist, SDK version=v1.10.11-20240724-aeaa107e5
|
|
||||||
[08/15 11:11:00.762526][debug][12088][DeviceManager.cpp:30] DeviceManager init ...
|
|
||||||
[08/15 11:11:00.762542][info][12088][MfPal.cpp:105] createObPal: create WinPal!
|
|
||||||
[08/15 11:11:00.763193][debug][12088][MfPal.cpp:110] WmfPal init ...
|
|
||||||
[08/15 11:11:00.790457][debug][12088][MfPal.cpp:117] WmfPal created!
|
|
||||||
[08/15 11:11:00.790495][debug][12088][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
|
||||||
[08/15 11:11:00.815795][debug][12088][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
|
||||||
[08/15 11:11:00.816035][debug][12088][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
|
||||||
[08/15 11:11:00.816179][debug][12088][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
|
||||||
[08/15 11:11:00.816215][info][12088][DeviceManager.cpp:15] Current found device(s): (0)
|
|
||||||
[08/15 11:11:00.816652][debug][12088][DeviceManager.cpp:52] DeviceManager construct done!
|
|
||||||
[08/15 11:11:00.816690][debug][12088][Context.cpp:81] Context destroying ...
|
|
||||||
[08/15 11:11:00.816703][debug][12088][DeviceManager.cpp:56] DeviceManager destroy ...
|
|
||||||
[08/15 11:11:00.816712][debug][12088][DeviceManager.cpp:64] DeviceManager Destructors done
|
|
||||||
[08/15 11:11:00.960762][debug][12088][MfPal.cpp:128] WmfPal destroyed!
|
|
||||||
[08/15 11:11:00.961818][info][12088][Context.cpp:84] Context destroyed
|
|
||||||
[08/15 11:17:16.080184][debug][27992][Context.cpp:30] Context creating, work_dir=D:\Trae_space\BodyBalanceEvaluation\frontend\src\renderer\dist-electron\win-unpacked\resources\backend
|
|
||||||
[08/15 11:17:16.080326][debug][27992][Context.cpp:49] Config file version=1.1
|
|
||||||
[08/15 11:17:16.080380][debug][27992][FrameBufferManager.cpp:23] Max global frame buffer size updated! size=2048.000MB
|
|
||||||
[08/15 11:17:16.080407][info][27992][Context.cpp:68] Context created with config: default config!
|
|
||||||
[08/15 11:17:16.080471][info][27992][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 11:17:16.080501][debug][27992][DeviceManager.cpp:30] DeviceManager init ...
|
|
||||||
[08/15 11:17:16.080518][info][27992][MfPal.cpp:105] createObPal: create WinPal!
|
|
||||||
[08/15 11:17:16.080537][debug][27992][MfPal.cpp:110] WmfPal init ...
|
|
||||||
[08/15 11:17:16.106317][debug][27992][MfPal.cpp:117] WmfPal created!
|
|
||||||
[08/15 11:17:16.106358][debug][27992][DeviceManager.cpp:34] Enable USB Device Enumerator ...
|
|
||||||
[08/15 11:17:16.132353][debug][27992][EnumeratorLibusb.cpp:321] queryDevicesInfo done!
|
|
||||||
[08/15 11:17:16.132619][debug][27992][MfPal.cpp:216] Create WinEventDeviceWatcher!
|
|
||||||
[08/15 11:17:16.132822][debug][27992][UsbDeviceEnumerator.cpp:78] No matched usb device found!
|
|
||||||
[08/15 11:17:16.132867][info][27992][DeviceManager.cpp:15] Current found device(s): (0)
|
|
||||||
[08/15 11:17:16.132889][debug][27992][DeviceManager.cpp:52] DeviceManager construct done!
|
|
||||||
[08/15 11:17:16.132917][debug][27992][Context.cpp:81] Context destroying ...
|
|
||||||
[08/15 11:17:16.132929][debug][27992][DeviceManager.cpp:56] DeviceManager destroy ...
|
|
||||||
[08/15 11:17:16.132938][debug][27992][DeviceManager.cpp:64] DeviceManager Destructors done
|
|
||||||
[08/15 11:17:16.274031][debug][27992][MfPal.cpp:128] WmfPal destroyed!
|
|
||||||
[08/15 11:17:16.274987][info][27992][Context.cpp:84] Context destroyed
|
|
||||||
|
@ -8,6 +8,7 @@ echo - 管理界面: http://localhost:5000
|
|||||||
echo.
|
echo.
|
||||||
echo 按Ctrl+C停止服务
|
echo 按Ctrl+C停止服务
|
||||||
echo.
|
echo.
|
||||||
|
cd BodyBalanceBackend
|
||||||
"BodyBalanceBackend.exe"
|
"BodyBalanceBackend.exe"
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
echo.
|
echo.
|
||||||
|
@ -11,7 +11,7 @@ let backendProcess;
|
|||||||
function startBackendService() {
|
function startBackendService() {
|
||||||
// 在打包后的应用中,使用process.resourcesPath获取resources目录
|
// 在打包后的应用中,使用process.resourcesPath获取resources目录
|
||||||
const resourcesPath = process.resourcesPath || path.join(__dirname, '../..');
|
const resourcesPath = process.resourcesPath || path.join(__dirname, '../..');
|
||||||
const backendPath = path.join(resourcesPath, 'backend/BodyBalanceBackend.exe');
|
const backendPath = path.join(resourcesPath, 'backend/BodyBalanceBackend/BodyBalanceBackend.exe');
|
||||||
const backendDir = path.join(resourcesPath, 'backend/');
|
const backendDir = path.join(resourcesPath, 'backend/');
|
||||||
|
|
||||||
console.log('Resources path:', resourcesPath);
|
console.log('Resources path:', resourcesPath);
|
||||||
@ -22,14 +22,15 @@ function startBackendService() {
|
|||||||
if (!fs.existsSync(backendPath)) {
|
if (!fs.existsSync(backendPath)) {
|
||||||
console.error('Backend executable not found:', backendPath);
|
console.error('Backend executable not found:', backendPath);
|
||||||
// 尝试备用路径
|
// 尝试备用路径
|
||||||
const fallbackPath = path.join(__dirname, 'resources/backend/BodyBalanceBackend.exe');
|
const fallbackPath = path.join(__dirname, 'resources/backend/BodyBalanceBackend/BodyBalanceBackend.exe');
|
||||||
console.log('Trying fallback path:', fallbackPath);
|
console.log('Trying fallback path:', fallbackPath);
|
||||||
if (!fs.existsSync(fallbackPath)) {
|
if (!fs.existsSync(fallbackPath)) {
|
||||||
console.error('Fallback backend executable not found:', fallbackPath);
|
console.error('Fallback backend executable not found:', fallbackPath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 使用备用路径
|
// 使用备用路径
|
||||||
const fallbackDir = path.join(__dirname, 'resources/backend/');
|
const fallbackDir = path.join(__dirname, 'resources/backend/BodyBalanceBackend/');
|
||||||
|
|
||||||
backendProcess = spawn(fallbackPath, [], {
|
backendProcess = spawn(fallbackPath, [], {
|
||||||
cwd: fallbackDir,
|
cwd: fallbackDir,
|
||||||
stdio: ['ignore', 'pipe', 'pipe']
|
stdio: ['ignore', 'pipe', 'pipe']
|
||||||
|
301
设备管理优化方案.md
Normal file
301
设备管理优化方案.md
Normal file
@ -0,0 +1,301 @@
|
|||||||
|
# 设备管理优化方案
|
||||||
|
|
||||||
|
## 1. 现状分析
|
||||||
|
|
||||||
|
### 1.1 当前架构问题
|
||||||
|
|
||||||
|
当前的 `device_manager.py` 文件(3694行)存在以下问题:
|
||||||
|
|
||||||
|
1. **单一职责原则违反**:一个类管理四种不同类型的设备
|
||||||
|
2. **代码耦合度高**:设备间相互依赖,一个设备故障可能影响其他设备
|
||||||
|
3. **维护困难**:代码量庞大,修改一个设备功能可能影响其他设备
|
||||||
|
4. **性能瓶颈**:所有设备共享同一个推流线程池,资源竞争严重
|
||||||
|
5. **扩展性差**:添加新设备类型需要修改核心管理器
|
||||||
|
6. **测试复杂**:单元测试需要模拟所有设备
|
||||||
|
|
||||||
|
### 1.2 当前设备类型
|
||||||
|
|
||||||
|
- **FemtoBolt深度相机**:负责身体姿态检测和深度图像采集
|
||||||
|
- **普通相机**:负责足部监控视频流
|
||||||
|
- **IMU传感器**:负责头部姿态数据采集
|
||||||
|
- **压力板传感器**:负责足底压力数据采集
|
||||||
|
|
||||||
|
## 2. 优化方案设计
|
||||||
|
|
||||||
|
### 2.1 架构设计原则
|
||||||
|
|
||||||
|
1. **单一职责原则**:每个设备类只负责自身的管理
|
||||||
|
2. **开闭原则**:对扩展开放,对修改封闭
|
||||||
|
3. **依赖倒置原则**:依赖抽象而非具体实现
|
||||||
|
4. **接口隔离原则**:设备间通过标准接口通信
|
||||||
|
|
||||||
|
### 2.2 目标架构
|
||||||
|
|
||||||
|
```
|
||||||
|
设备管理系统
|
||||||
|
├── 抽象基类 (BaseDevice)
|
||||||
|
├── FemtoBolt深度相机管理器 (FemtoBoltManager)
|
||||||
|
├── 普通相机管理器 (CameraManager)
|
||||||
|
├── IMU传感器管理器 (IMUManager)
|
||||||
|
├── 压力板管理器 (PressureManager)
|
||||||
|
└── 设备协调器 (DeviceCoordinator)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/devices/
|
||||||
|
├── __init__.py
|
||||||
|
├── base_device.py # 抽象基类
|
||||||
|
├── femtobolt_manager.py # FemtoBolt深度相机管理
|
||||||
|
├── camera_manager.py # 普通相机管理
|
||||||
|
├── imu_manager.py # IMU传感器管理
|
||||||
|
├── pressure_manager.py # 压力板管理
|
||||||
|
├── device_coordinator.py # 设备协调器
|
||||||
|
└── utils/
|
||||||
|
├── __init__.py
|
||||||
|
├── socket_manager.py # Socket连接管理
|
||||||
|
└── config_manager.py # 配置管理
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 详细设计
|
||||||
|
|
||||||
|
### 3.1 抽象基类设计
|
||||||
|
|
||||||
|
```python
|
||||||
|
# base_device.py
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Dict, Any, Optional
|
||||||
|
import threading
|
||||||
|
import logging
|
||||||
|
|
||||||
|
class BaseDevice(ABC):
|
||||||
|
"""设备抽象基类"""
|
||||||
|
|
||||||
|
def __init__(self, device_name: str, config: Dict[str, Any]):
|
||||||
|
self.device_name = device_name
|
||||||
|
self.config = config
|
||||||
|
self.is_connected = False
|
||||||
|
self.is_streaming = False
|
||||||
|
self.socket_namespace = f"/{device_name}"
|
||||||
|
self.logger = logging.getLogger(f"device.{device_name}")
|
||||||
|
self._lock = threading.RLock()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def initialize(self) -> bool:
|
||||||
|
"""初始化设备"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def calibrate(self) -> Dict[str, Any]:
|
||||||
|
"""校准设备"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def start_streaming(self, socketio) -> bool:
|
||||||
|
"""启动数据推流"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def stop_streaming(self) -> bool:
|
||||||
|
"""停止数据推流"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_status(self) -> Dict[str, Any]:
|
||||||
|
"""获取设备状态"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def cleanup(self) -> None:
|
||||||
|
"""清理资源"""
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 FemtoBolt深度相机管理器
|
||||||
|
|
||||||
|
```python
|
||||||
|
# femtobolt_manager.py
|
||||||
|
class FemtoBoltManager(BaseDevice):
|
||||||
|
"""FemtoBolt深度相机管理器"""
|
||||||
|
|
||||||
|
def __init__(self, config: Dict[str, Any]):
|
||||||
|
super().__init__("femtobolt", config)
|
||||||
|
self.camera = None
|
||||||
|
self.streaming_thread = None
|
||||||
|
self.frame_cache = {}
|
||||||
|
|
||||||
|
def initialize(self) -> bool:
|
||||||
|
"""初始化FemtoBolt深度相机"""
|
||||||
|
try:
|
||||||
|
# FemtoBolt初始化逻辑
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error(f"FemtoBolt初始化失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def start_streaming(self, socketio) -> bool:
|
||||||
|
"""启动深度图像推流"""
|
||||||
|
# 独立的Socket.IO命名空间
|
||||||
|
# 独立的推流线程
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 设备协调器
|
||||||
|
|
||||||
|
```python
|
||||||
|
# device_coordinator.py
|
||||||
|
class DeviceCoordinator:
|
||||||
|
"""设备协调器 - 管理所有设备的生命周期"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.devices = {}
|
||||||
|
self.socketio = None
|
||||||
|
|
||||||
|
def register_device(self, device: BaseDevice):
|
||||||
|
"""注册设备"""
|
||||||
|
self.devices[device.device_name] = device
|
||||||
|
|
||||||
|
def initialize_all(self) -> Dict[str, bool]:
|
||||||
|
"""初始化所有设备"""
|
||||||
|
results = {}
|
||||||
|
for name, device in self.devices.items():
|
||||||
|
results[name] = device.initialize()
|
||||||
|
return results
|
||||||
|
|
||||||
|
def start_all_streaming(self) -> Dict[str, bool]:
|
||||||
|
"""启动所有设备推流"""
|
||||||
|
results = {}
|
||||||
|
for name, device in self.devices.items():
|
||||||
|
if device.is_connected:
|
||||||
|
results[name] = device.start_streaming(self.socketio)
|
||||||
|
return results
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 优势分析
|
||||||
|
|
||||||
|
### 4.1 性能优势
|
||||||
|
|
||||||
|
1. **并行处理**:每个设备独立的Socket.IO命名空间,减少数据传输冲突
|
||||||
|
2. **资源隔离**:每个设备独立的线程池,避免资源竞争
|
||||||
|
3. **内存优化**:设备级别的缓存管理,减少内存占用
|
||||||
|
4. **故障隔离**:单个设备故障不影响其他设备运行
|
||||||
|
|
||||||
|
### 4.2 开发优势
|
||||||
|
|
||||||
|
1. **代码可维护性**:每个设备类代码量控制在500-800行
|
||||||
|
2. **团队协作**:不同开发者可以并行开发不同设备
|
||||||
|
3. **单元测试**:每个设备可以独立测试
|
||||||
|
4. **版本控制**:设备功能变更影响范围小
|
||||||
|
|
||||||
|
### 4.3 扩展优势
|
||||||
|
|
||||||
|
1. **新设备接入**:只需实现BaseDevice接口
|
||||||
|
2. **功能扩展**:设备功能扩展不影响其他设备
|
||||||
|
3. **配置管理**:每个设备独立配置文件
|
||||||
|
4. **部署灵活**:可以选择性部署某些设备
|
||||||
|
|
||||||
|
## 5. 劣势分析
|
||||||
|
|
||||||
|
### 5.1 复杂性增加
|
||||||
|
|
||||||
|
1. **架构复杂度**:从单一类变为多类协作
|
||||||
|
2. **通信开销**:设备间通信需要额外的协调机制
|
||||||
|
3. **状态同步**:多设备状态同步复杂度增加
|
||||||
|
|
||||||
|
### 5.2 开发成本
|
||||||
|
|
||||||
|
1. **重构工作量**:需要大量重构现有代码
|
||||||
|
2. **测试工作量**:需要重新设计集成测试
|
||||||
|
3. **文档更新**:需要更新相关文档和API
|
||||||
|
|
||||||
|
### 5.3 运维复杂度
|
||||||
|
|
||||||
|
1. **监控复杂**:需要监控多个独立服务
|
||||||
|
2. **故障排查**:跨设备问题排查难度增加
|
||||||
|
3. **配置管理**:多个配置文件管理复杂
|
||||||
|
|
||||||
|
## 6. 实施方案
|
||||||
|
|
||||||
|
### 6.1 分阶段实施
|
||||||
|
|
||||||
|
#### 第一阶段:基础架构搭建(1-2周)
|
||||||
|
- 创建抽象基类和工具类
|
||||||
|
- 设计Socket.IO命名空间方案
|
||||||
|
- 搭建设备协调器框架
|
||||||
|
|
||||||
|
#### 第二阶段:设备迁移(3-4周)
|
||||||
|
- 按优先级迁移设备:Camera → IMU → Pressure → FemtoBolt
|
||||||
|
- 每个设备迁移后进行充分测试
|
||||||
|
- 保持向后兼容性
|
||||||
|
|
||||||
|
#### 第三阶段:优化和集成(1-2周)
|
||||||
|
- 性能优化和内存管理
|
||||||
|
- 集成测试和压力测试
|
||||||
|
- 文档更新和代码审查
|
||||||
|
|
||||||
|
### 6.2 风险控制
|
||||||
|
|
||||||
|
1. **渐进式迁移**:保留原有代码作为备份
|
||||||
|
2. **功能开关**:通过配置控制使用新旧架构
|
||||||
|
3. **充分测试**:每个阶段都进行完整测试
|
||||||
|
4. **回滚方案**:准备快速回滚到原架构的方案
|
||||||
|
|
||||||
|
### 6.3 Socket.IO命名空间设计
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 前端连接示例
|
||||||
|
const cameraSocket = io('/camera');
|
||||||
|
const femtoboltSocket = io('/femtobolt');
|
||||||
|
const imuSocket = io('/imu');
|
||||||
|
const pressureSocket = io('/pressure');
|
||||||
|
|
||||||
|
// 独立的事件监听
|
||||||
|
cameraSocket.on('video_frame', handleCameraFrame);
|
||||||
|
femtoboltSocket.on('depth_frame', handleDepthFrame);
|
||||||
|
imuSocket.on('imu_data', handleIMUData);
|
||||||
|
pressureSocket.on('pressure_data', handlePressureData);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 性能预期
|
||||||
|
|
||||||
|
### 7.1 性能提升预期
|
||||||
|
|
||||||
|
- **并发处理能力**:提升40-60%
|
||||||
|
- **内存使用效率**:降低20-30%
|
||||||
|
- **故障恢复时间**:减少50-70%
|
||||||
|
- **开发效率**:提升30-50%
|
||||||
|
|
||||||
|
### 7.2 资源消耗
|
||||||
|
|
||||||
|
- **CPU使用**:可能增加5-10%(多线程开销)
|
||||||
|
- **内存使用**:减少20-30%(更好的缓存管理)
|
||||||
|
- **网络带宽**:基本持平(优化的数据传输)
|
||||||
|
|
||||||
|
## 8. 结论和建议
|
||||||
|
|
||||||
|
### 8.1 可行性评估
|
||||||
|
|
||||||
|
**高度可行** - 该优化方案在技术上完全可行,且能显著改善系统的可维护性和性能。
|
||||||
|
|
||||||
|
### 8.2 推荐实施
|
||||||
|
|
||||||
|
**强烈推荐** - 考虑到当前代码的复杂度和未来的扩展需求,建议尽快实施该优化方案。
|
||||||
|
|
||||||
|
### 8.3 关键成功因素
|
||||||
|
|
||||||
|
1. **充分的测试**:确保每个阶段都有完整的测试覆盖
|
||||||
|
2. **团队协作**:需要前后端团队密切配合
|
||||||
|
3. **渐进式实施**:避免一次性大规模重构的风险
|
||||||
|
4. **性能监控**:实施过程中持续监控系统性能
|
||||||
|
|
||||||
|
### 8.4 后续优化方向
|
||||||
|
|
||||||
|
1. **微服务化**:将设备管理器进一步拆分为独立的微服务
|
||||||
|
2. **容器化部署**:使用Docker容器化部署各个设备服务
|
||||||
|
3. **负载均衡**:为高负载设备添加负载均衡机制
|
||||||
|
4. **监控告警**:建立完善的设备监控和告警系统
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*本优化方案基于对现有代码的深入分析,结合软件工程最佳实践制定。实施过程中应根据实际情况灵活调整。*
|
Loading…
Reference in New Issue
Block a user