BodyBalanceEvaluation/backend/tests/test_smitsense_dll.py
2025-08-07 16:22:38 +08:00

479 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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测试程序结束")