1096 lines
38 KiB
Python
1096 lines
38 KiB
Python
"""
|
||
设备管理器模块
|
||
负责发现、管理和控制各种触觉反馈设备
|
||
"""
|
||
|
||
import time
|
||
from typing import Dict, Any, List, Optional
|
||
import platform
|
||
import threading
|
||
import math
|
||
|
||
class DeviceType:
|
||
"""设备类型常量"""
|
||
GAMEPAD = "gamepad"
|
||
VR_CONTROLLER = "vr_controller"
|
||
HAPTIC_GLOVE = "haptic_glove"
|
||
VEST = "vest"
|
||
SEAT = "seat"
|
||
WHEEL = "wheel"
|
||
CUSTOM = "custom"
|
||
SMARTPHONE = "smartphone"
|
||
WATCH = "watch"
|
||
EXOSUIT = "exosuit"
|
||
|
||
class ConnectionType:
|
||
"""连接类型常量"""
|
||
USB = "usb"
|
||
BLUETOOTH = "bluetooth"
|
||
WIRELESS = "wireless"
|
||
BUILT_IN = "built_in"
|
||
NETWORK = "network"
|
||
|
||
class HapticDeviceManager:
|
||
"""
|
||
触觉设备管理器
|
||
负责发现、管理和控制各种触觉反馈设备
|
||
"""
|
||
|
||
def __init__(self, plugin):
|
||
"""
|
||
初始化触觉设备管理器
|
||
|
||
Args:
|
||
plugin: 触觉反馈系统插件实例
|
||
"""
|
||
self.plugin = plugin
|
||
self.enabled = False
|
||
self.initialized = False
|
||
|
||
# 设备字典
|
||
self.devices = {}
|
||
self.device_counter = 0
|
||
|
||
# 已连接设备
|
||
self.connected_devices = {}
|
||
|
||
# 设备发现配置
|
||
self.discovery_config = {
|
||
'auto_discovery': True,
|
||
'discovery_interval': 5.0,
|
||
'supported_platforms': ['Windows', 'Linux', 'Darwin'],
|
||
'supported_devices': [
|
||
DeviceType.GAMEPAD,
|
||
DeviceType.VR_CONTROLLER,
|
||
DeviceType.HAPTIC_GLOVE,
|
||
DeviceType.VEST,
|
||
DeviceType.SEAT,
|
||
DeviceType.WHEEL,
|
||
DeviceType.SMARTPHONE,
|
||
DeviceType.WATCH,
|
||
DeviceType.EXOSUIT
|
||
],
|
||
'bluetooth_discovery': True,
|
||
'usb_discovery': True,
|
||
'network_discovery': True
|
||
}
|
||
|
||
# 平台特定配置
|
||
self.platform_config = {
|
||
'Windows': {
|
||
'api': 'xinput',
|
||
'libraries': ['pydirectinput', 'xinput'],
|
||
'features': ['xinput', 'directinput'],
|
||
'device_paths': ['\\\\.\\PhysicalDrive0']
|
||
},
|
||
'Linux': {
|
||
'api': 'udev',
|
||
'libraries': ['evdev', 'pygame'],
|
||
'features': ['udev', 'evdev'],
|
||
'device_paths': ['/dev/input', '/dev/hidraw']
|
||
},
|
||
'Darwin': { # macOS
|
||
'api': 'iokit',
|
||
'libraries': ['pyobjc'],
|
||
'features': ['corehaptics', 'iokit'],
|
||
'device_paths': ['/dev/']
|
||
}
|
||
}
|
||
|
||
# 设备能力映射
|
||
self.device_capabilities = {
|
||
DeviceType.GAMEPAD: [
|
||
'left_rumble', 'right_rumble', 'trigger_rumble',
|
||
'high_frequency', 'low_frequency', 'adaptive_triggers'
|
||
],
|
||
DeviceType.VR_CONTROLLER: [
|
||
'rumble', 'texture_feedback', 'temperature_feedback',
|
||
'force_feedback', 'vibration_patterns', 'haptic_positioning'
|
||
],
|
||
DeviceType.HAPTIC_GLOVE: [
|
||
'finger_vibration', 'palm_vibration', 'force_feedback',
|
||
'texture_simulation', 'temperature_simulation', 'gesture_feedback'
|
||
],
|
||
DeviceType.VEST: [
|
||
'full_body_vibration', 'localized_vibration',
|
||
'directional_feedback', 'pressure_points', 'impact_simulation'
|
||
],
|
||
DeviceType.SEAT: [
|
||
'low_frequency_rumble', 'vibration_patterns',
|
||
'directional_feedback', 'motion_simulation', 'bass_shakers'
|
||
],
|
||
DeviceType.WHEEL: [
|
||
'force_feedback', 'vibration', 'road_texture',
|
||
'collision_feedback', 'gear_shift', 'damper_effects'
|
||
],
|
||
DeviceType.SMARTPHONE: [
|
||
'simple_vibration', 'pattern_vibration', 'amplitude_control'
|
||
],
|
||
DeviceType.WATCH: [
|
||
'taptic_engine', 'notification_feedback', 'haptic_notifications'
|
||
],
|
||
DeviceType.EXOSUIT: [
|
||
'full_body_actuation', 'muscle_simulation', 'balance_feedback',
|
||
'force_amplification', 'movement_guidance'
|
||
]
|
||
}
|
||
|
||
# 设备区域映射
|
||
self.device_zones = {
|
||
DeviceType.GAMEPAD: ['left_handle', 'right_handle', 'triggers'],
|
||
DeviceType.VR_CONTROLLER: ['handle', 'buttons', 'touchpad'],
|
||
DeviceType.HAPTIC_GLOVE: ['thumb', 'index', 'middle', 'ring', 'pinky', 'palm'],
|
||
DeviceType.VEST: ['front', 'back', 'left', 'right', 'top', 'bottom'],
|
||
DeviceType.SEAT: ['seat_base', 'seat_back', 'left_side', 'right_side'],
|
||
DeviceType.WHEEL: ['wheel', 'pedals', 'shifter'],
|
||
DeviceType.SMARTPHONE: ['back_panel'],
|
||
DeviceType.WATCH: ['back_panel'],
|
||
DeviceType.EXOSUIT: ['legs', 'arms', 'torso', 'feet']
|
||
}
|
||
|
||
# 设备状态
|
||
self.device_states = {
|
||
'scanning': False,
|
||
'last_scan': 0.0,
|
||
'devices_found': 0,
|
||
'bluetooth_connected': 0,
|
||
'usb_connected': 0
|
||
}
|
||
|
||
# 统计信息
|
||
self.stats = {
|
||
'devices_registered': 0,
|
||
'devices_connected': 0,
|
||
'devices_disconnected': 0,
|
||
'scan_operations': 0,
|
||
'haptic_effects': 0,
|
||
'device_errors': 0,
|
||
'data_transmitted': 0
|
||
}
|
||
|
||
# 线程管理
|
||
self.discovery_thread = None
|
||
self.running = False
|
||
|
||
# 回调函数
|
||
self.device_callbacks = {
|
||
'device_connected': [],
|
||
'device_disconnected': [],
|
||
'device_updated': [],
|
||
'haptic_effect_applied': [],
|
||
'device_error': []
|
||
}
|
||
|
||
# 设备配置
|
||
self.device_config = {
|
||
'default_intensity': 0.8,
|
||
'default_frequency': 50.0,
|
||
'max_intensity': 1.0,
|
||
'min_frequency': 1.0,
|
||
'max_frequency': 300.0,
|
||
'response_time': 0.01, # 10ms响应时间
|
||
'enable_safety_limits': True
|
||
}
|
||
|
||
# 设备缓存
|
||
self.device_cache = {}
|
||
|
||
# 时间戳记录
|
||
self.last_discovery_time = 0.0
|
||
self.last_state_update = 0.0
|
||
|
||
print("✓ 触觉设备管理器已创建")
|
||
|
||
def initialize(self) -> bool:
|
||
"""
|
||
初始化触觉设备管理器
|
||
|
||
Returns:
|
||
是否初始化成功
|
||
"""
|
||
try:
|
||
# 检查平台支持
|
||
current_platform = platform.system()
|
||
if current_platform not in self.discovery_config['supported_platforms']:
|
||
print(f"⚠ 平台未完全支持: {current_platform}")
|
||
|
||
# 初始化平台特定功能
|
||
self._initialize_platform_features()
|
||
|
||
# 创建初始设备
|
||
self._create_default_devices()
|
||
|
||
# 初始化设备缓存
|
||
self._initialize_device_cache()
|
||
|
||
self.initialized = True
|
||
print("✓ 触觉设备管理器初始化完成")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉设备管理器初始化失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def enable(self) -> bool:
|
||
"""
|
||
启用触觉设备管理器
|
||
|
||
Returns:
|
||
是否启用成功
|
||
"""
|
||
try:
|
||
if not self.initialized:
|
||
print("✗ 触觉设备管理器未初始化")
|
||
return False
|
||
|
||
self.enabled = True
|
||
self.running = True
|
||
|
||
# 启动设备发现线程
|
||
if self.discovery_config['auto_discovery']:
|
||
self.discovery_thread = threading.Thread(target=self._discovery_loop, daemon=True)
|
||
self.discovery_thread.start()
|
||
|
||
print("✓ 触觉设备管理器已启用")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉设备管理器启用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def disable(self):
|
||
"""禁用触觉设备管理器"""
|
||
try:
|
||
self.enabled = False
|
||
self.running = False
|
||
|
||
# 等待发现线程结束
|
||
if self.discovery_thread and self.discovery_thread.is_alive():
|
||
self.discovery_thread.join(timeout=2.0)
|
||
|
||
# 断开所有设备
|
||
self._disconnect_all_devices()
|
||
|
||
print("✓ 触觉设备管理器已禁用")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉设备管理器禁用失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def finalize(self):
|
||
"""清理触觉设备管理器资源"""
|
||
try:
|
||
self.disable()
|
||
self.devices.clear()
|
||
self.connected_devices.clear()
|
||
self.device_states.clear()
|
||
self.device_callbacks.clear()
|
||
self.device_cache.clear()
|
||
self.initialized = False
|
||
print("✓ 触觉设备管理器资源已清理")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉设备管理器资源清理失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def update(self, dt: float):
|
||
"""
|
||
更新触觉设备管理器状态
|
||
|
||
Args:
|
||
dt: 时间增量
|
||
"""
|
||
try:
|
||
if not self.enabled:
|
||
return
|
||
|
||
current_time = time.time()
|
||
|
||
# 定期更新设备状态
|
||
if current_time - self.last_state_update > 1.0: # 每秒更新一次
|
||
self._update_device_states()
|
||
self.last_state_update = current_time
|
||
|
||
# 更新统计信息
|
||
self.stats['devices_connected'] = len(self.connected_devices)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉设备管理器更新失败: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
def _initialize_platform_features(self):
|
||
"""初始化平台特定功能"""
|
||
try:
|
||
current_platform = platform.system()
|
||
platform_info = self.platform_config.get(current_platform, {})
|
||
|
||
print(f"✓ 平台初始化: {current_platform}")
|
||
print(f" API: {platform_info.get('api', 'unknown')}")
|
||
print(f" 特性: {', '.join(platform_info.get('features', []))}")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 平台功能初始化失败: {e}")
|
||
|
||
def _initialize_device_cache(self):
|
||
"""初始化设备缓存"""
|
||
try:
|
||
# 预创建常用设备的配置模板
|
||
for device_type in self.device_capabilities:
|
||
self.device_cache[device_type] = {
|
||
'capabilities': self.device_capabilities[device_type],
|
||
'zones': self.device_zones.get(device_type, []),
|
||
'default_config': self._get_default_device_config(device_type)
|
||
}
|
||
|
||
print("✓ 设备缓存初始化完成")
|
||
except Exception as e:
|
||
print(f"✗ 设备缓存初始化失败: {e}")
|
||
|
||
def _get_default_device_config(self, device_type: str) -> Dict[str, Any]:
|
||
"""
|
||
获取设备默认配置
|
||
|
||
Args:
|
||
device_type: 设备类型
|
||
|
||
Returns:
|
||
默认配置字典
|
||
"""
|
||
base_config = {
|
||
'intensity_scale': 1.0,
|
||
'frequency_scale': 1.0,
|
||
'response_curve': 'linear',
|
||
'max_actuators': 1,
|
||
'min_update_interval': 0.01
|
||
}
|
||
|
||
# 根据设备类型添加特定配置
|
||
if device_type == DeviceType.HAPTIC_GLOVE:
|
||
base_config.update({
|
||
'max_actuators': 6, # 5个手指+手掌
|
||
'independent_control': True
|
||
})
|
||
elif device_type == DeviceType.VEST:
|
||
base_config.update({
|
||
'max_actuators': 6, # 6个区域
|
||
'spatial_resolution': True
|
||
})
|
||
elif device_type == DeviceType.EXOSUIT:
|
||
base_config.update({
|
||
'max_actuators': 16, # 多部位控制
|
||
'force_feedback': True,
|
||
'position_tracking': True
|
||
})
|
||
|
||
return base_config
|
||
|
||
def _create_default_devices(self):
|
||
"""创建默认设备"""
|
||
try:
|
||
current_platform = platform.system()
|
||
|
||
# 创建默认游戏手柄
|
||
gamepad_id = self.register_device(
|
||
device_type=DeviceType.GAMEPAD,
|
||
name=f"系统游戏手柄 ({current_platform})",
|
||
connection_type=ConnectionType.BUILT_IN,
|
||
vendor_id="system",
|
||
product_id="gamepad",
|
||
actuators=2 # 左右马达
|
||
)
|
||
|
||
# 创建默认智能手机
|
||
phone_id = self.register_device(
|
||
device_type=DeviceType.SMARTPHONE,
|
||
name=f"系统智能手机 ({current_platform})",
|
||
connection_type=ConnectionType.BUILT_IN,
|
||
vendor_id="system",
|
||
product_id="smartphone",
|
||
actuators=1 # 单一振动马达
|
||
)
|
||
|
||
# 标记为已连接
|
||
if gamepad_id >= 0:
|
||
self.connect_device(gamepad_id)
|
||
if phone_id >= 0:
|
||
self.connect_device(phone_id)
|
||
|
||
print("✓ 默认设备创建完成")
|
||
|
||
except Exception as e:
|
||
print(f"✗ 默认设备创建失败: {e}")
|
||
|
||
def _discovery_loop(self):
|
||
"""设备发现循环"""
|
||
try:
|
||
discovery_interval = self.discovery_config['discovery_interval']
|
||
|
||
while self.running:
|
||
if self.enabled and self.discovery_config['auto_discovery']:
|
||
self.scan_for_devices()
|
||
|
||
time.sleep(discovery_interval)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备发现循环失败: {e}")
|
||
|
||
def _update_device_states(self):
|
||
"""更新设备状态"""
|
||
try:
|
||
current_time = time.time()
|
||
|
||
# 检查已连接设备的状态
|
||
devices_to_disconnect = []
|
||
for device_id, device_info in self.connected_devices.items():
|
||
# 检查设备是否仍然连接
|
||
if not self._is_device_connected(device_id):
|
||
devices_to_disconnect.append(device_id)
|
||
|
||
# 断开已丢失的设备
|
||
for device_id in devices_to_disconnect:
|
||
self.disconnect_device(device_id)
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备状态更新失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
|
||
def _is_device_connected(self, device_id: int) -> bool:
|
||
"""
|
||
检查设备是否仍然连接
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
是否连接
|
||
"""
|
||
try:
|
||
# 这里应该实现实际的设备连接检查逻辑
|
||
# 简化处理,假设设备一直连接
|
||
if device_id in self.devices:
|
||
# 模拟设备连接状态检查
|
||
device_info = self.devices[device_id]
|
||
last_seen = device_info.get('last_seen', 0)
|
||
# 如果超过10秒没有更新,认为设备断开
|
||
return (time.time() - last_seen) < 10.0
|
||
return False
|
||
except Exception as e:
|
||
print(f"✗ 设备连接检查失败: {e}")
|
||
return True
|
||
|
||
def _disconnect_all_devices(self):
|
||
"""断开所有设备"""
|
||
try:
|
||
device_ids = list(self.connected_devices.keys())
|
||
for device_id in device_ids:
|
||
self.disconnect_device(device_id)
|
||
except Exception as e:
|
||
print(f"✗ 断开所有设备失败: {e}")
|
||
|
||
def register_device(self, device_type: str, name: str, connection_type: str,
|
||
vendor_id: str, product_id: str,
|
||
capabilities: List[str] = None, actuators: int = 1) -> int:
|
||
"""
|
||
注册设备
|
||
|
||
Args:
|
||
device_type: 设备类型
|
||
name: 设备名称
|
||
connection_type: 连接类型
|
||
vendor_id: 厂商ID
|
||
product_id: 产品ID
|
||
capabilities: 设备功能列表
|
||
actuators: 执行器数量
|
||
|
||
Returns:
|
||
设备ID
|
||
"""
|
||
try:
|
||
device_id = self.device_counter
|
||
self.device_counter += 1
|
||
|
||
# 如果未提供功能列表,使用默认功能
|
||
if capabilities is None:
|
||
capabilities = self.device_capabilities.get(device_type, [])
|
||
|
||
device_info = {
|
||
'id': device_id,
|
||
'type': device_type,
|
||
'name': name,
|
||
'connection_type': connection_type,
|
||
'vendor_id': vendor_id,
|
||
'product_id': product_id,
|
||
'capabilities': capabilities,
|
||
'actuators': actuators,
|
||
'registered_time': time.time(),
|
||
'connected': False,
|
||
'last_seen': 0.0,
|
||
'battery_level': 100.0, # 电池电量百分比
|
||
'signal_strength': 100.0, # 信号强度百分比
|
||
'firmware_version': '1.0.0',
|
||
'hardware_version': '1.0.0',
|
||
'haptic_state': {}, # 触觉状态
|
||
'zones': self.device_zones.get(device_type, []),
|
||
'config': self.device_cache.get(device_type, {}).get('default_config', {}),
|
||
'supported_effects': ['simple', 'periodic', 'envelope'],
|
||
'max_intensity': 1.0,
|
||
'min_frequency': 1.0,
|
||
'max_frequency': 300.0,
|
||
'response_time': 0.01
|
||
}
|
||
|
||
# 根据设备类型添加特定支持的效果
|
||
if device_type in [DeviceType.HAPTIC_GLOVE, DeviceType.VEST, DeviceType.EXOSUIT]:
|
||
device_info['supported_effects'].extend(['texture', 'wind', 'water'])
|
||
if device_type in [DeviceType.VR_CONTROLLER, DeviceType.WHEEL]:
|
||
device_info['supported_effects'].extend(['impulse', 'explosion'])
|
||
|
||
self.devices[device_id] = device_info
|
||
self.stats['devices_registered'] += 1
|
||
|
||
print(f"✓ 设备已注册: {name} (ID: {device_id})")
|
||
return device_id
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备注册失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return -1
|
||
|
||
def unregister_device(self, device_id: int) -> bool:
|
||
"""
|
||
注销设备
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
是否注销成功
|
||
"""
|
||
try:
|
||
if device_id in self.devices:
|
||
device_info = self.devices[device_id]
|
||
device_name = device_info['name']
|
||
|
||
# 如果设备已连接,先断开连接
|
||
if device_id in self.connected_devices:
|
||
self.disconnect_device(device_id)
|
||
|
||
del self.devices[device_id]
|
||
print(f"✓ 设备已注销: {device_name} (ID: {device_id})")
|
||
return True
|
||
else:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备注销失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def connect_device(self, device_id: int) -> bool:
|
||
"""
|
||
连接设备
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
是否连接成功
|
||
"""
|
||
try:
|
||
if device_id not in self.devices:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
|
||
device_info = self.devices[device_id]
|
||
if device_info['connected']:
|
||
print(f"⚠ 设备已连接: {device_info['name']} (ID: {device_id})")
|
||
return True
|
||
|
||
# 模拟设备连接过程
|
||
device_info['connected'] = True
|
||
device_info['last_seen'] = time.time()
|
||
self.connected_devices[device_id] = device_info
|
||
|
||
# 更新连接统计
|
||
conn_type = device_info['connection_type']
|
||
if conn_type == ConnectionType.BLUETOOTH:
|
||
self.device_states['bluetooth_connected'] += 1
|
||
elif conn_type == ConnectionType.USB:
|
||
self.device_states['usb_connected'] += 1
|
||
|
||
# 触发连接回调
|
||
self._trigger_device_callback('device_connected', {
|
||
'device_id': device_id,
|
||
'device_info': device_info
|
||
})
|
||
|
||
self.stats['devices_connected'] += 1
|
||
print(f"✓ 设备已连接: {device_info['name']} (ID: {device_id})")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备连接失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def disconnect_device(self, device_id: int) -> bool:
|
||
"""
|
||
断开设备连接
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
是否断开成功
|
||
"""
|
||
try:
|
||
if device_id not in self.devices:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
|
||
device_info = self.devices[device_id]
|
||
if not device_info['connected']:
|
||
print(f"⚠ 设备未连接: {device_info['name']} (ID: {device_id})")
|
||
return True
|
||
|
||
# 断开设备连接
|
||
device_info['connected'] = False
|
||
if device_id in self.connected_devices:
|
||
del self.connected_devices[device_id]
|
||
|
||
# 更新连接统计
|
||
conn_type = device_info['connection_type']
|
||
if conn_type == ConnectionType.BLUETOOTH:
|
||
self.device_states['bluetooth_connected'] = max(0, self.device_states['bluetooth_connected'] - 1)
|
||
elif conn_type == ConnectionType.USB:
|
||
self.device_states['usb_connected'] = max(0, self.device_states['usb_connected'] - 1)
|
||
|
||
# 触发断开回调
|
||
self._trigger_device_callback('device_disconnected', {
|
||
'device_id': device_id,
|
||
'device_info': device_info
|
||
})
|
||
|
||
self.stats['devices_disconnected'] += 1
|
||
print(f"✓ 设备已断开: {device_info['name']} (ID: {device_id})")
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备断开失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def scan_for_devices(self) -> List[int]:
|
||
"""
|
||
扫描设备
|
||
|
||
Returns:
|
||
发现的设备ID列表
|
||
"""
|
||
try:
|
||
self.device_states['scanning'] = True
|
||
self.device_states['last_scan'] = time.time()
|
||
|
||
discovered_devices = []
|
||
|
||
# 模拟设备发现过程
|
||
# 在实际实现中,这里会根据平台调用相应的API来发现设备
|
||
|
||
# 检查现有设备的状态
|
||
for device_id, device_info in self.devices.items():
|
||
# 模拟设备发现
|
||
if not device_info['connected']:
|
||
# 有一定概率"发现"设备
|
||
import random
|
||
if random.random() < 0.1: # 10%概率
|
||
discovered_devices.append(device_id)
|
||
|
||
self.device_states['devices_found'] = len(discovered_devices)
|
||
self.stats['scan_operations'] += 1
|
||
|
||
if discovered_devices:
|
||
print(f"✓ 发现 {len(discovered_devices)} 个设备")
|
||
|
||
return discovered_devices
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备扫描失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return []
|
||
finally:
|
||
self.device_states['scanning'] = False
|
||
|
||
def apply_haptic_effect(self, device_id: int, intensity: float,
|
||
frequency: float, progress: float,
|
||
zone: str = None, effect_type: str = 'simple') -> bool:
|
||
"""
|
||
应用触觉效果到设备
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
intensity: 强度(0.0-1.0)
|
||
frequency: 频率
|
||
progress: 进度(0.0-1.0)
|
||
zone: 设备区域
|
||
effect_type: 效果类型
|
||
|
||
Returns:
|
||
是否应用成功
|
||
"""
|
||
try:
|
||
# 检查设备是否存在
|
||
if device_id is not None and device_id not in self.devices:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
|
||
# 检查设备是否连接
|
||
if device_id is not None and not self.devices[device_id]['connected']:
|
||
print(f"✗ 设备未连接: ID {device_id}")
|
||
return False
|
||
|
||
# 限制参数范围
|
||
intensity = max(0.0, min(1.0, intensity))
|
||
frequency = max(0.0, frequency)
|
||
progress = max(0.0, min(1.0, progress))
|
||
|
||
# 应用设备配置限制
|
||
if device_id is not None:
|
||
device_info = self.devices[device_id]
|
||
intensity *= device_info.get('max_intensity', 1.0)
|
||
frequency = max(
|
||
device_info.get('min_frequency', 1.0),
|
||
min(device_info.get('max_frequency', 300.0), frequency)
|
||
)
|
||
|
||
# 检查设备是否支持该效果类型
|
||
supported_effects = device_info.get('supported_effects', ['simple'])
|
||
if effect_type not in supported_effects:
|
||
print(f"⚠ 设备不支持效果类型: {effect_type}")
|
||
# 降级到简单效果
|
||
effect_type = 'simple'
|
||
|
||
# 更新设备触觉状态
|
||
if device_id is not None:
|
||
device_info = self.devices[device_id]
|
||
device_info['haptic_state'] = {
|
||
'intensity': intensity,
|
||
'frequency': frequency,
|
||
'progress': progress,
|
||
'zone': zone,
|
||
'effect_type': effect_type,
|
||
'timestamp': time.time()
|
||
}
|
||
device_info['last_seen'] = time.time()
|
||
|
||
# 模拟数据传输
|
||
data_size = 32 # 模拟32字节数据
|
||
self.stats['data_transmitted'] += data_size
|
||
|
||
# 触发触觉效果应用回调
|
||
self._trigger_device_callback('haptic_effect_applied', {
|
||
'device_id': device_id,
|
||
'intensity': intensity,
|
||
'frequency': frequency,
|
||
'progress': progress,
|
||
'zone': zone,
|
||
'effect_type': effect_type,
|
||
'data_size': data_size
|
||
})
|
||
|
||
self.stats['haptic_effects'] += 1
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 触觉效果应用失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def get_device(self, device_id: int) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
获取设备信息
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
设备信息字典或None
|
||
"""
|
||
return self.devices.get(device_id)
|
||
|
||
def get_connected_devices(self) -> Dict[int, Dict[str, Any]]:
|
||
"""
|
||
获取所有已连接的设备
|
||
|
||
Returns:
|
||
已连接设备字典
|
||
"""
|
||
return self.connected_devices.copy()
|
||
|
||
def get_devices_by_type(self, device_type: str) -> List[Dict[str, Any]]:
|
||
"""
|
||
根据类型获取设备列表
|
||
|
||
Args:
|
||
device_type: 设备类型
|
||
|
||
Returns:
|
||
设备信息列表
|
||
"""
|
||
try:
|
||
devices = []
|
||
for device_info in self.devices.values():
|
||
if device_info['type'] == device_type:
|
||
devices.append(device_info)
|
||
return devices
|
||
except Exception as e:
|
||
print(f"✗ 按类型获取设备失败: {e}")
|
||
return []
|
||
|
||
def update_device_battery(self, device_id: int, battery_level: float):
|
||
"""
|
||
更新设备电池电量
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
battery_level: 电池电量百分比(0-100)
|
||
"""
|
||
try:
|
||
if device_id in self.devices:
|
||
self.devices[device_id]['battery_level'] = max(0.0, min(100.0, battery_level))
|
||
except Exception as e:
|
||
print(f"✗ 设备电池电量更新失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
|
||
def update_device_signal(self, device_id: int, signal_strength: float):
|
||
"""
|
||
更新设备信号强度
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
signal_strength: 信号强度百分比(0-100)
|
||
"""
|
||
try:
|
||
if device_id in self.devices:
|
||
self.devices[device_id]['signal_strength'] = max(0.0, min(100.0, signal_strength))
|
||
except Exception as e:
|
||
print(f"✗ 设备信号强度更新失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
|
||
def set_device_config(self, device_id: int, config: Dict[str, Any]) -> bool:
|
||
"""
|
||
设置设备配置
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
config: 配置字典
|
||
|
||
Returns:
|
||
是否设置成功
|
||
"""
|
||
try:
|
||
if device_id in self.devices:
|
||
self.devices[device_id]['config'].update(config)
|
||
print(f"✓ 设备配置已更新: ID {device_id}")
|
||
return True
|
||
else:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
except Exception as e:
|
||
print(f"✗ 设备配置设置失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def get_device_config(self, device_id: int) -> Optional[Dict[str, Any]]:
|
||
"""
|
||
获取设备配置
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
配置字典或None
|
||
"""
|
||
try:
|
||
if device_id in self.devices:
|
||
return self.devices[device_id].get('config', {})
|
||
return None
|
||
except Exception as e:
|
||
print(f"✗ 设备配置获取失败: {e}")
|
||
return None
|
||
|
||
def calibrate_device(self, device_id: int) -> bool:
|
||
"""
|
||
校准设备
|
||
|
||
Args:
|
||
device_id: 设备ID
|
||
|
||
Returns:
|
||
是否校准成功
|
||
"""
|
||
try:
|
||
if device_id not in self.devices:
|
||
print(f"✗ 设备不存在: ID {device_id}")
|
||
return False
|
||
|
||
device_info = self.devices[device_id]
|
||
print(f"✓ 设备校准完成: {device_info['name']} (ID: {device_id})")
|
||
|
||
# 更新校准时间
|
||
device_info['last_calibrated'] = time.time()
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"✗ 设备校准失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
return False
|
||
|
||
def _trigger_device_callback(self, callback_type: str, data: Dict[str, Any]):
|
||
"""
|
||
触发设备回调
|
||
|
||
Args:
|
||
callback_type: 回调类型
|
||
data: 回调数据
|
||
"""
|
||
try:
|
||
if callback_type in self.device_callbacks:
|
||
for callback in self.device_callbacks[callback_type]:
|
||
try:
|
||
callback(data)
|
||
except Exception as e:
|
||
print(f"✗ 设备回调执行失败: {e}")
|
||
except Exception as e:
|
||
print(f"✗ 设备回调触发失败: {e}")
|
||
|
||
def register_device_callback(self, callback_type: str, callback: callable):
|
||
"""
|
||
注册设备回调
|
||
|
||
Args:
|
||
callback_type: 回调类型
|
||
callback: 回调函数
|
||
"""
|
||
try:
|
||
if callback_type in self.device_callbacks:
|
||
self.device_callbacks[callback_type].append(callback)
|
||
print(f"✓ 设备回调已注册: {callback_type}")
|
||
else:
|
||
print(f"✗ 无效的回调类型: {callback_type}")
|
||
except Exception as e:
|
||
print(f"✗ 设备回调注册失败: {e}")
|
||
|
||
def unregister_device_callback(self, callback_type: str, callback: callable):
|
||
"""
|
||
注销设备回调
|
||
|
||
Args:
|
||
callback_type: 回调类型
|
||
callback: 回调函数
|
||
"""
|
||
try:
|
||
if callback_type in self.device_callbacks:
|
||
if callback in self.device_callbacks[callback_type]:
|
||
self.device_callbacks[callback_type].remove(callback)
|
||
print(f"✓ 设备回调已注销: {callback_type}")
|
||
except Exception as e:
|
||
print(f"✗ 设备回调注销失败: {e}")
|
||
|
||
def get_device_capabilities(self, device_type: str) -> List[str]:
|
||
"""
|
||
获取设备类型的功能列表
|
||
|
||
Args:
|
||
device_type: 设备类型
|
||
|
||
Returns:
|
||
功能列表
|
||
"""
|
||
return self.device_capabilities.get(device_type, [])
|
||
|
||
def get_device_zones(self, device_type: str) -> List[str]:
|
||
"""
|
||
获取设备区域列表
|
||
|
||
Args:
|
||
device_type: 设备类型
|
||
|
||
Returns:
|
||
区域列表
|
||
"""
|
||
return self.device_zones.get(device_type, [])
|
||
|
||
def get_platform_config(self) -> Dict[str, Any]:
|
||
"""
|
||
获取平台配置
|
||
|
||
Returns:
|
||
平台配置字典
|
||
"""
|
||
current_platform = platform.system()
|
||
return self.platform_config.get(current_platform, {})
|
||
|
||
def set_discovery_config(self, config: Dict[str, Any]):
|
||
"""
|
||
设置设备发现配置
|
||
|
||
Args:
|
||
config: 发现配置字典
|
||
"""
|
||
try:
|
||
self.discovery_config.update(config)
|
||
print(f"✓ 设备发现配置已更新: {self.discovery_config}")
|
||
except Exception as e:
|
||
print(f"✗ 设备发现配置设置失败: {e}")
|
||
self.stats['device_errors'] += 1
|
||
|
||
def get_discovery_config(self) -> Dict[str, Any]:
|
||
"""
|
||
获取设备发现配置
|
||
|
||
Returns:
|
||
发现配置字典
|
||
"""
|
||
return self.discovery_config.copy()
|
||
|
||
def get_device_stats(self) -> Dict[str, Any]:
|
||
"""
|
||
获取设备统计信息
|
||
|
||
Returns:
|
||
统计信息字典
|
||
"""
|
||
return self.stats.copy()
|
||
|
||
def reset_device_stats(self):
|
||
"""重置设备统计信息"""
|
||
try:
|
||
self.stats = {
|
||
'devices_registered': 0,
|
||
'devices_connected': 0,
|
||
'devices_disconnected': 0,
|
||
'scan_operations': 0,
|
||
'haptic_effects': 0,
|
||
'device_errors': 0,
|
||
'data_transmitted': 0
|
||
}
|
||
print("✓ 设备统计信息已重置")
|
||
except Exception as e:
|
||
print(f"✗ 设备统计信息重置失败: {e}")
|
||
|
||
def get_device_states(self) -> Dict[str, Any]:
|
||
"""
|
||
获取设备状态
|
||
|
||
Returns:
|
||
设备状态字典
|
||
"""
|
||
return self.device_states.copy() |