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