BodyBalanceEvaluation/backend/tests/test_smitsense_dll.py

479 lines
16 KiB
Python
Raw Normal View History

2025-08-07 16:22:38 +08:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SMiTSense足部压力传感器DLL测试程序
测试SMiTSenseUsb-F3.0.dll的Python接口调用
"""
import ctypes
import os
import sys
import time
from ctypes import Structure, c_int, c_float, c_char_p, c_void_p, c_uint32, POINTER, byref
import logging
# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class SMiTSensePressureSensor:
"""
SMiTSense足部压力传感器Python接口类
"""
def __init__(self, dll_path=None):
"""
初始化SMiTSense压力传感器
Args:
dll_path: DLL文件路径如果为None则使用默认路径
"""
self.dll = None
self.device_handle = None
self.is_connected = False
# 设置DLL路径
if dll_path is None:
dll_path = os.path.join(os.path.dirname(__file__), 'SMiTSenseUsb-F3.0.dll')
self.dll_path = dll_path
self._load_dll()
def _load_dll(self):
"""
加载SMiTSense DLL并设置函数签名
"""
try:
if not os.path.exists(self.dll_path):
raise FileNotFoundError(f"DLL文件未找到: {self.dll_path}")
# 加载DLL
self.dll = ctypes.WinDLL(self.dll_path)
logger.info(f"成功加载DLL: {self.dll_path}")
# 设置函数签名
self._setup_function_signatures()
except Exception as e:
logger.error(f"加载DLL失败: {e}")
raise
def _setup_function_signatures(self):
"""
设置DLL函数的参数类型和返回类型
"""
try:
# fpms_usb_init - 初始化USB连接
self.dll.fpms_usb_init.argtypes = []
self.dll.fpms_usb_init.restype = c_int
# fpms_usb_get_device_list - 获取设备列表
self.dll.fpms_usb_get_device_list.argtypes = [POINTER(c_int)]
self.dll.fpms_usb_get_device_list.restype = c_int
# fpms_usb_open - 打开设备
self.dll.fpms_usb_open.argtypes = [c_int]
self.dll.fpms_usb_open.restype = c_void_p
# fpms_usb_close - 关闭设备
self.dll.fpms_usb_close.argtypes = [c_void_p]
self.dll.fpms_usb_close.restype = c_int
# fpms_usb_read_frame - 读取压力数据帧
self.dll.fpms_usb_read_frame.argtypes = [c_void_p, POINTER(c_float), c_int]
self.dll.fpms_usb_read_frame.restype = c_int
# fpms_usb_get_sensitivity - 获取灵敏度
self.dll.fpms_usb_get_sensitivity.argtypes = [c_void_p, POINTER(c_float)]
self.dll.fpms_usb_get_sensitivity.restype = c_int
# fpms_usb_config_sensitivity - 配置灵敏度
self.dll.fpms_usb_config_sensitivity.argtypes = [c_void_p, c_float]
self.dll.fpms_usb_config_sensitivity.restype = c_int
logger.info("DLL函数签名设置完成")
except AttributeError as e:
logger.error(f"设置函数签名失败,可能是函数名不匹配: {e}")
raise
def initialize(self):
"""
初始化USB连接
Returns:
bool: 初始化是否成功
"""
try:
result = self.dll.fpms_usb_init()
if result == 0:
logger.info("USB连接初始化成功")
return True
else:
logger.error(f"USB连接初始化失败错误码: {result}")
return False
except Exception as e:
logger.error(f"初始化异常: {e}")
return False
def get_device_list(self):
"""
获取可用设备列表
Returns:
list: 设备ID列表
"""
try:
device_count = c_int()
result = self.dll.fpms_usb_get_device_list(byref(device_count))
if result == 0:
count = device_count.value
logger.info(f"发现 {count} 个SMiTSense设备")
return list(range(count))
else:
logger.error(f"获取设备列表失败,错误码: {result}")
return []
except Exception as e:
logger.error(f"获取设备列表异常: {e}")
return []
def connect(self, device_id=0):
"""
连接到指定设备
Args:
device_id: 设备ID默认为0
Returns:
bool: 连接是否成功
"""
try:
self.device_handle = self.dll.fpms_usb_open(device_id)
if self.device_handle:
self.is_connected = True
logger.info(f"成功连接到设备 {device_id}")
return True
else:
logger.error(f"连接设备 {device_id} 失败")
return False
except Exception as e:
logger.error(f"连接设备异常: {e}")
return False
def disconnect(self):
"""
断开设备连接
Returns:
bool: 断开是否成功
"""
try:
if self.device_handle and self.is_connected:
result = self.dll.fpms_usb_close(self.device_handle)
if result == 0:
self.is_connected = False
self.device_handle = None
logger.info("设备连接已断开")
return True
else:
logger.error(f"断开连接失败,错误码: {result}")
return False
else:
logger.warning("设备未连接,无需断开")
return True
except Exception as e:
logger.error(f"断开连接异常: {e}")
return False
def read_pressure_data(self, sensor_count=16):
"""
读取压力传感器数据
Args:
sensor_count: 传感器数量默认16个
Returns:
list: 压力值列表如果失败返回None
"""
try:
if not self.is_connected or not self.device_handle:
logger.error("设备未连接")
return None
# 创建压力数据缓冲区
pressure_data = (c_float * sensor_count)()
result = self.dll.fpms_usb_read_frame(
self.device_handle,
pressure_data,
sensor_count
)
if result == 0:
# 转换为Python列表
data_list = [pressure_data[i] for i in range(sensor_count)]
logger.debug(f"读取压力数据成功: {data_list}")
return data_list
else:
logger.error(f"读取压力数据失败,错误码: {result}")
return None
except Exception as e:
logger.error(f"读取压力数据异常: {e}")
return None
def get_sensitivity(self):
"""
获取传感器灵敏度
Returns:
float: 灵敏度值如果失败返回None
"""
try:
if not self.is_connected or not self.device_handle:
logger.error("设备未连接")
return None
sensitivity = c_float()
result = self.dll.fpms_usb_get_sensitivity(self.device_handle, byref(sensitivity))
if result == 0:
value = sensitivity.value
logger.info(f"当前灵敏度: {value}")
return value
else:
logger.error(f"获取灵敏度失败,错误码: {result}")
return None
except Exception as e:
logger.error(f"获取灵敏度异常: {e}")
return None
def set_sensitivity(self, sensitivity_value):
"""
设置传感器灵敏度
Args:
sensitivity_value: 灵敏度值
Returns:
bool: 设置是否成功
"""
try:
if not self.is_connected or not self.device_handle:
logger.error("设备未连接")
return False
result = self.dll.fpms_usb_config_sensitivity(
self.device_handle,
c_float(sensitivity_value)
)
if result == 0:
logger.info(f"灵敏度设置成功: {sensitivity_value}")
return True
else:
logger.error(f"设置灵敏度失败,错误码: {result}")
return False
except Exception as e:
logger.error(f"设置灵敏度异常: {e}")
return False
def get_foot_pressure_zones(self, pressure_data):
"""
将原始压力数据转换为足部区域压力
Args:
pressure_data: 原始压力数据列表
Returns:
dict: 足部各区域压力数据
"""
if not pressure_data or len(pressure_data) < 16:
return None
try:
# 假设16个传感器的布局可根据实际传感器布局调整
# 左脚前部: 传感器 0-3
# 左脚后部: 传感器 4-7
# 右脚前部: 传感器 8-11
# 右脚后部: 传感器 12-15
left_front = sum(pressure_data[0:4])
left_rear = sum(pressure_data[4:8])
right_front = sum(pressure_data[8:12])
right_rear = sum(pressure_data[12:16])
left_total = left_front + left_rear
right_total = right_front + right_rear
total_pressure = left_total + right_total
return {
'left_front': left_front,
'left_rear': left_rear,
'right_front': right_front,
'right_rear': right_rear,
'left_total': left_total,
'right_total': right_total,
'total_pressure': total_pressure,
'raw_data': pressure_data
}
except Exception as e:
logger.error(f"处理足部压力区域数据异常: {e}")
return None
def test_smitsense_sensor():
"""
测试SMiTSense压力传感器的主要功能
"""
logger.info("开始SMiTSense压力传感器测试")
# 创建传感器实例
sensor = SMiTSensePressureSensor()
try:
# 1. 初始化
logger.info("1. 初始化USB连接...")
if not sensor.initialize():
logger.error("初始化失败,测试终止")
return False
# 2. 获取设备列表
logger.info("2. 获取设备列表...")
devices = sensor.get_device_list()
if not devices:
logger.warning("未发现SMiTSense设备")
return False
logger.info(f"发现设备: {devices}")
# 3. 连接第一个设备
logger.info("3. 连接设备...")
if not sensor.connect(devices[0]):
logger.error("连接设备失败")
return False
# 4. 获取当前灵敏度
logger.info("4. 获取传感器灵敏度...")
sensitivity = sensor.get_sensitivity()
if sensitivity is not None:
logger.info(f"当前灵敏度: {sensitivity}")
# 5. 设置新的灵敏度(可选)
logger.info("5. 设置传感器灵敏度...")
if sensor.set_sensitivity(1.0):
logger.info("灵敏度设置成功")
# 6. 读取压力数据
logger.info("6. 开始读取压力数据...")
for i in range(10): # 读取10次数据
pressure_data = sensor.read_pressure_data()
if pressure_data:
# 转换为足部区域数据
foot_zones = sensor.get_foot_pressure_zones(pressure_data)
if foot_zones:
logger.info(f"{i+1}次读取:")
logger.info(f" 左脚前部: {foot_zones['left_front']:.2f}")
logger.info(f" 左脚后部: {foot_zones['left_rear']:.2f}")
logger.info(f" 右脚前部: {foot_zones['right_front']:.2f}")
logger.info(f" 右脚后部: {foot_zones['right_rear']:.2f}")
logger.info(f" 总压力: {foot_zones['total_pressure']:.2f}")
else:
logger.warning(f"{i+1}次读取: 数据处理失败")
else:
logger.warning(f"{i+1}次读取: 无数据")
time.sleep(0.1) # 等待100ms
logger.info("压力数据读取测试完成")
return True
except Exception as e:
logger.error(f"测试过程中发生异常: {e}")
return False
finally:
# 7. 断开连接
logger.info("7. 断开设备连接...")
sensor.disconnect()
logger.info("SMiTSense压力传感器测试结束")
def test_dll_functions():
"""
测试DLL函数的基本调用不需要实际硬件
"""
logger.info("开始DLL函数基本调用测试")
try:
sensor = SMiTSensePressureSensor()
logger.info("DLL加载成功")
# 测试初始化函数
logger.info("测试初始化函数...")
result = sensor.initialize()
logger.info(f"初始化结果: {result}")
# 测试获取设备列表
logger.info("测试获取设备列表...")
devices = sensor.get_device_list()
logger.info(f"设备列表: {devices}")
logger.info("DLL函数基本调用测试完成")
return True
except Exception as e:
logger.error(f"DLL函数测试失败: {e}")
return False
if __name__ == "__main__":
print("SMiTSense足部压力传感器DLL测试程序")
print("=" * 50)
# 检查DLL文件是否存在
dll_path = os.path.join(os.path.dirname(__file__), 'SMiTSenseUsb-F3.0.dll')
if not os.path.exists(dll_path):
print(f"错误: DLL文件不存在 - {dll_path}")
print("请确保SMiTSenseUsb-F3.0.dll文件在当前目录中")
sys.exit(1)
print(f"DLL文件路径: {dll_path}")
print()
# 运行测试
try:
# 首先测试DLL基本功能
print("1. DLL基本功能测试")
print("-" * 30)
if test_dll_functions():
print("✅ DLL基本功能测试通过")
else:
print("❌ DLL基本功能测试失败")
print()
# 然后测试完整的传感器功能(需要硬件)
print("2. 完整传感器功能测试(需要硬件连接)")
print("-" * 30)
if test_smitsense_sensor():
print("✅ 传感器功能测试通过")
else:
print("❌ 传感器功能测试失败(可能是硬件未连接)")
except KeyboardInterrupt:
print("\n用户中断测试")
except Exception as e:
print(f"\n测试过程中发生未处理的异常: {e}")
import traceback
traceback.print_exc()
print("\n测试程序结束")