739 lines
24 KiB
Python
739 lines
24 KiB
Python
"""
|
|
事件处理器模块
|
|
负责处理语音控制相关的事件
|
|
"""
|
|
|
|
import time
|
|
from typing import Dict, Any, List, Optional, Callable
|
|
import threading
|
|
import queue
|
|
|
|
class VoiceEventHandler:
|
|
"""
|
|
事件处理器
|
|
负责处理语音控制相关的事件
|
|
"""
|
|
|
|
def __init__(self, plugin):
|
|
"""
|
|
初始化事件处理器
|
|
|
|
Args:
|
|
plugin: 语音控制插件实例
|
|
"""
|
|
self.plugin = plugin
|
|
self.enabled = False
|
|
self.initialized = False
|
|
|
|
# 事件队列
|
|
self.event_queue = queue.Queue(maxsize=100)
|
|
|
|
# 事件监听器
|
|
self.event_listeners = {}
|
|
|
|
# 事件配置
|
|
self.event_config = {
|
|
'enable_event_queue': True,
|
|
'max_queue_size': 100,
|
|
'enable_event_filtering': True,
|
|
'filter_duplicate_events': True,
|
|
'duplicate_time_window': 1.0,
|
|
'enable_async_processing': True,
|
|
'max_processing_threads': 4
|
|
}
|
|
|
|
# 事件统计
|
|
self.event_stats = {
|
|
'events_received': 0,
|
|
'events_processed': 0,
|
|
'events_dropped': 0,
|
|
'events_filtered': 0,
|
|
'processing_errors': 0,
|
|
'average_processing_time': 0.0
|
|
}
|
|
|
|
# 事件历史
|
|
self.event_history = []
|
|
self.max_history_size = 1000
|
|
|
|
# 线程管理
|
|
self.processing_threads = []
|
|
self.running = False
|
|
|
|
# 回调函数
|
|
self.event_callbacks = {
|
|
'event_received': [],
|
|
'event_processed': [],
|
|
'event_error': [],
|
|
'event_queue_full': []
|
|
}
|
|
|
|
# 时间戳记录
|
|
self.last_event_time = 0.0
|
|
self.last_processing_time = 0.0
|
|
|
|
# 重复事件跟踪
|
|
self.recent_events = {}
|
|
|
|
print("✓ 事件处理器已创建")
|
|
|
|
def initialize(self) -> bool:
|
|
"""
|
|
初始化事件处理器
|
|
|
|
Returns:
|
|
是否初始化成功
|
|
"""
|
|
try:
|
|
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.event_config['enable_async_processing']:
|
|
thread_count = min(self.event_config['max_processing_threads'], 4)
|
|
for i in range(thread_count):
|
|
thread = threading.Thread(target=self._processing_loop, daemon=True,
|
|
name=f"EventProcessor-{i}")
|
|
self.processing_threads.append(thread)
|
|
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
|
|
|
|
# 等待处理线程结束
|
|
for thread in self.processing_threads:
|
|
if thread.is_alive():
|
|
thread.join(timeout=1.0)
|
|
|
|
self.processing_threads.clear()
|
|
|
|
print("✓ 事件处理器已禁用")
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件处理器禁用失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def finalize(self):
|
|
"""清理事件处理器资源"""
|
|
try:
|
|
self.disable()
|
|
self.event_listeners.clear()
|
|
self.event_callbacks.clear()
|
|
|
|
# 清空事件队列
|
|
while not self.event_queue.empty():
|
|
try:
|
|
self.event_queue.get_nowait()
|
|
except queue.Empty:
|
|
break
|
|
|
|
self.event_history.clear()
|
|
self.recent_events.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()
|
|
self.last_event_time = current_time
|
|
|
|
# 清理过期的重复事件记录
|
|
self._cleanup_recent_events(current_time)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件处理器更新失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
def _processing_loop(self):
|
|
"""事件处理循环"""
|
|
try:
|
|
while self.running and self.enabled:
|
|
try:
|
|
# 从队列获取事件
|
|
if not self.event_queue.empty():
|
|
event_data = self.event_queue.get_nowait()
|
|
self._process_event(event_data)
|
|
else:
|
|
time.sleep(0.01)
|
|
|
|
except queue.Empty:
|
|
time.sleep(0.01)
|
|
except Exception as e:
|
|
print(f"✗ 事件处理循环错误: {e}")
|
|
time.sleep(0.1)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件处理循环失败: {e}")
|
|
|
|
def _cleanup_recent_events(self, current_time: float):
|
|
"""清理过期的重复事件记录"""
|
|
try:
|
|
expired_events = [
|
|
event_key for event_key, event_time in self.recent_events.items()
|
|
if current_time - event_time > self.event_config['duplicate_time_window']
|
|
]
|
|
|
|
for event_key in expired_events:
|
|
del self.recent_events[event_key]
|
|
|
|
except Exception as e:
|
|
print(f"✗ 重复事件清理失败: {e}")
|
|
|
|
def post_event(self, event_type: str, event_data: Dict[str, Any] = None) -> bool:
|
|
"""
|
|
发布事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
|
|
Returns:
|
|
是否发布成功
|
|
"""
|
|
try:
|
|
if not self.enabled:
|
|
print("✗ 事件处理器未启用")
|
|
return False
|
|
|
|
# 创建事件对象
|
|
event = {
|
|
'type': event_type,
|
|
'data': event_data or {},
|
|
'timestamp': time.time(),
|
|
'id': f"{event_type}_{int(time.time() * 1000000)}"
|
|
}
|
|
|
|
# 触发事件接收回调
|
|
self._trigger_event_callback('event_received', event)
|
|
|
|
# 更新统计信息
|
|
self.event_stats['events_received'] += 1
|
|
|
|
# 事件过滤
|
|
if self.event_config['enable_event_filtering']:
|
|
if not self._filter_event(event):
|
|
self.event_stats['events_filtered'] += 1
|
|
return True
|
|
|
|
# 检查重复事件
|
|
if self.event_config['filter_duplicate_events']:
|
|
if self._is_duplicate_event(event):
|
|
self.event_stats['events_filtered'] += 1
|
|
return True
|
|
|
|
# 添加到事件队列
|
|
if self.event_config['enable_event_queue']:
|
|
try:
|
|
self.event_queue.put_nowait(event)
|
|
|
|
# 记录事件历史
|
|
self._record_event_history(event)
|
|
|
|
return True
|
|
except queue.Full:
|
|
self.event_stats['events_dropped'] += 1
|
|
print("✗ 事件队列已满,丢弃事件")
|
|
|
|
# 触发队列满回调
|
|
self._trigger_event_callback('event_queue_full', {
|
|
'event': event,
|
|
'queue_size': self.event_queue.qsize()
|
|
})
|
|
|
|
return False
|
|
else:
|
|
# 直接处理事件
|
|
return self._process_event(event)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件发布失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return False
|
|
|
|
def _filter_event(self, event: Dict[str, Any]) -> bool:
|
|
"""
|
|
过滤事件
|
|
|
|
Args:
|
|
event: 事件对象
|
|
|
|
Returns:
|
|
是否通过过滤
|
|
"""
|
|
try:
|
|
# 这里可以实现具体的事件过滤逻辑
|
|
# 例如:根据事件类型、优先级等进行过滤
|
|
|
|
# 示例:过滤掉低置信度的语音识别事件
|
|
if event['type'] == 'speech_recognized':
|
|
confidence = event['data'].get('confidence', 1.0)
|
|
if confidence < 0.3: # 置信度阈值
|
|
return False
|
|
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件过滤失败: {e}")
|
|
return True # 默认通过过滤
|
|
|
|
def _is_duplicate_event(self, event: Dict[str, Any]) -> bool:
|
|
"""
|
|
检查是否为重复事件
|
|
|
|
Args:
|
|
event: 事件对象
|
|
|
|
Returns:
|
|
是否为重复事件
|
|
"""
|
|
try:
|
|
# 创建事件键
|
|
event_key = f"{event['type']}_{hash(str(event['data']))}"
|
|
current_time = time.time()
|
|
|
|
# 检查是否在时间窗口内已存在相同事件
|
|
if event_key in self.recent_events:
|
|
last_time = self.recent_events[event_key]
|
|
if current_time - last_time < self.event_config['duplicate_time_window']:
|
|
return True
|
|
|
|
# 记录当前事件时间
|
|
self.recent_events[event_key] = current_time
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ 重复事件检查失败: {e}")
|
|
return False
|
|
|
|
def _process_event(self, event: Dict[str, Any]) -> bool:
|
|
"""
|
|
处理事件
|
|
|
|
Args:
|
|
event: 事件对象
|
|
|
|
Returns:
|
|
是否处理成功
|
|
"""
|
|
try:
|
|
start_time = time.time()
|
|
|
|
event_type = event['type']
|
|
event_data = event['data']
|
|
|
|
# 查找事件监听器
|
|
listeners = self.event_listeners.get(event_type, [])
|
|
|
|
if listeners:
|
|
# 调用所有监听器
|
|
for listener in listeners:
|
|
try:
|
|
listener(event_type, event_data)
|
|
except Exception as e:
|
|
print(f"✗ 事件监听器执行失败: {e}")
|
|
self.event_stats['processing_errors'] += 1
|
|
|
|
# 触发事件错误回调
|
|
self._trigger_event_callback('event_error', {
|
|
'event': event,
|
|
'error': str(e),
|
|
'listener': listener.__name__ if hasattr(listener, '__name__') else 'unknown'
|
|
})
|
|
|
|
# 更新统计信息
|
|
self.event_stats['events_processed'] += 1
|
|
|
|
# 触发事件处理回调
|
|
self._trigger_event_callback('event_processed', event)
|
|
|
|
# 计算处理时间
|
|
processing_time = time.time() - start_time
|
|
self.event_stats['average_processing_time'] = (
|
|
(self.event_stats['average_processing_time'] * (self.event_stats['events_processed'] - 1) +
|
|
processing_time) / self.event_stats['events_processed']
|
|
)
|
|
|
|
return True
|
|
else:
|
|
# 没有监听器,但事件仍被处理
|
|
self.event_stats['events_processed'] += 1
|
|
self._trigger_event_callback('event_processed', event)
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件处理失败: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
self.event_stats['processing_errors'] += 1
|
|
|
|
# 触发事件错误回调
|
|
self._trigger_event_callback('event_error', {
|
|
'event': event,
|
|
'error': str(e),
|
|
'listener': 'processor'
|
|
})
|
|
|
|
return False
|
|
|
|
def _record_event_history(self, event: Dict[str, Any]):
|
|
"""
|
|
记录事件历史
|
|
|
|
Args:
|
|
event: 事件对象
|
|
"""
|
|
try:
|
|
self.event_history.append(event)
|
|
|
|
# 保持历史记录大小
|
|
if len(self.event_history) > self.max_history_size:
|
|
self.event_history.pop(0)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件历史记录失败: {e}")
|
|
|
|
def register_event_listener(self, event_type: str, listener: Callable) -> bool:
|
|
"""
|
|
注册事件监听器
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
listener: 监听器函数
|
|
|
|
Returns:
|
|
是否注册成功
|
|
"""
|
|
try:
|
|
if event_type not in self.event_listeners:
|
|
self.event_listeners[event_type] = []
|
|
|
|
self.event_listeners[event_type].append(listener)
|
|
print(f"✓ 事件监听器已注册: {event_type}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件监听器注册失败: {e}")
|
|
return False
|
|
|
|
def unregister_event_listener(self, event_type: str, listener: Callable) -> bool:
|
|
"""
|
|
注销事件监听器
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
listener: 监听器函数
|
|
|
|
Returns:
|
|
是否注销成功
|
|
"""
|
|
try:
|
|
if event_type in self.event_listeners:
|
|
if listener in self.event_listeners[event_type]:
|
|
self.event_listeners[event_type].remove(listener)
|
|
print(f"✓ 事件监听器已注销: {event_type}")
|
|
return True
|
|
|
|
print(f"✗ 事件监听器不存在: {event_type}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件监听器注销失败: {e}")
|
|
return False
|
|
|
|
def get_event_listeners(self) -> Dict[str, List[Callable]]:
|
|
"""
|
|
获取事件监听器
|
|
|
|
Returns:
|
|
事件监听器字典
|
|
"""
|
|
return {k: v.copy() for k, v in self.event_listeners.items()}
|
|
|
|
def get_event_queue_size(self) -> int:
|
|
"""
|
|
获取事件队列大小
|
|
|
|
Returns:
|
|
队列大小
|
|
"""
|
|
return self.event_queue.qsize()
|
|
|
|
def clear_event_queue(self) -> bool:
|
|
"""
|
|
清空事件队列
|
|
|
|
Returns:
|
|
是否清空成功
|
|
"""
|
|
try:
|
|
while not self.event_queue.empty():
|
|
try:
|
|
self.event_queue.get_nowait()
|
|
except queue.Empty:
|
|
break
|
|
|
|
print("✓ 事件队列已清空")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"✗ 事件队列清空失败: {e}")
|
|
return False
|
|
|
|
def get_event_history(self) -> List[Dict[str, Any]]:
|
|
"""
|
|
获取事件历史
|
|
|
|
Returns:
|
|
事件历史列表
|
|
"""
|
|
return self.event_history.copy()
|
|
|
|
def clear_event_history(self):
|
|
"""清空事件历史"""
|
|
try:
|
|
self.event_history.clear()
|
|
print("✓ 事件历史已清空")
|
|
except Exception as e:
|
|
print(f"✗ 事件历史清空失败: {e}")
|
|
|
|
def set_event_config(self, config: Dict[str, Any]) -> bool:
|
|
"""
|
|
设置事件配置
|
|
|
|
Args:
|
|
config: 配置字典
|
|
|
|
Returns:
|
|
是否设置成功
|
|
"""
|
|
try:
|
|
self.event_config.update(config)
|
|
print(f"✓ 事件配置已更新: {self.event_config}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ 事件配置设置失败: {e}")
|
|
return False
|
|
|
|
def get_event_config(self) -> Dict[str, Any]:
|
|
"""
|
|
获取事件配置
|
|
|
|
Returns:
|
|
配置字典
|
|
"""
|
|
return self.event_config.copy()
|
|
|
|
def _trigger_event_callback(self, callback_type: str, data: Dict[str, Any]):
|
|
"""
|
|
触发事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
data: 回调数据
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
for callback in self.event_callbacks[callback_type]:
|
|
try:
|
|
callback(data)
|
|
except Exception as e:
|
|
print(f"✗ 事件回调执行失败: {e}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调触发失败: {e}")
|
|
|
|
def register_event_callback(self, callback_type: str, callback: Callable):
|
|
"""
|
|
注册事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
self.event_callbacks[callback_type].append(callback)
|
|
print(f"✓ 事件回调已注册: {callback_type}")
|
|
else:
|
|
print(f"✗ 无效的回调类型: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调注册失败: {e}")
|
|
|
|
def unregister_event_callback(self, callback_type: str, callback: Callable):
|
|
"""
|
|
注销事件回调
|
|
|
|
Args:
|
|
callback_type: 回调类型
|
|
callback: 回调函数
|
|
"""
|
|
try:
|
|
if callback_type in self.event_callbacks:
|
|
if callback in self.event_callbacks[callback_type]:
|
|
self.event_callbacks[callback_type].remove(callback)
|
|
print(f"✓ 事件回调已注销: {callback_type}")
|
|
except Exception as e:
|
|
print(f"✗ 事件回调注销失败: {e}")
|
|
|
|
def get_stats(self) -> Dict[str, Any]:
|
|
"""
|
|
获取统计信息
|
|
|
|
Returns:
|
|
统计信息字典
|
|
"""
|
|
return self.event_stats.copy()
|
|
|
|
def reset_stats(self):
|
|
"""重置统计信息"""
|
|
try:
|
|
self.event_stats = {
|
|
'events_received': 0,
|
|
'events_processed': 0,
|
|
'events_dropped': 0,
|
|
'events_filtered': 0,
|
|
'processing_errors': 0,
|
|
'average_processing_time': 0.0
|
|
}
|
|
print("✓ 事件处理器统计信息已重置")
|
|
except Exception as e:
|
|
print(f"✗ 事件处理器统计信息重置失败: {e}")
|
|
|
|
# 常用事件处理方法
|
|
def handle_speech_recognized(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
处理语音识别事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
text = event_data.get('text', '')
|
|
confidence = event_data.get('confidence', 0.0)
|
|
|
|
print(f"🎤 语音识别事件: '{text}' (置信度: {confidence:.2f})")
|
|
|
|
# 传递给命令处理器
|
|
if self.plugin.command_processor:
|
|
self.plugin.command_processor.process_command(text, confidence)
|
|
|
|
except Exception as e:
|
|
print(f"✗ 语音识别事件处理失败: {e}")
|
|
|
|
def handle_speech_synthesis_started(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
处理语音合成开始事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
text = event_data.get('text', '')
|
|
print(f"🔊 语音合成开始: '{text}'")
|
|
except Exception as e:
|
|
print(f"✗ 语音合成开始事件处理失败: {e}")
|
|
|
|
def handle_speech_synthesis_completed(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
处理语音合成完成事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
text = event_data.get('text', '')
|
|
print(f"✅ 语音合成完成: '{text}'")
|
|
except Exception as e:
|
|
print(f"✗ 语音合成完成事件处理失败: {e}")
|
|
|
|
def handle_wake_word_detected(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
处理唤醒词检测事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
text = event_data.get('text', '')
|
|
confidence = event_data.get('confidence', 0.0)
|
|
print(f"🔔 唤醒词检测: '{text}' (置信度: {confidence:.2f})")
|
|
|
|
# 可以在这里添加特殊处理逻辑
|
|
if self.plugin.speech_synthesizer:
|
|
# 简单确认音
|
|
pass
|
|
|
|
except Exception as e:
|
|
print(f"✗ 唤醒词检测事件处理失败: {e}")
|
|
|
|
def handle_command_processed(self, event_type: str, event_data: Dict[str, Any]):
|
|
"""
|
|
处理命令处理事件
|
|
|
|
Args:
|
|
event_type: 事件类型
|
|
event_data: 事件数据
|
|
"""
|
|
try:
|
|
command_text = event_data.get('command_text', '')
|
|
original_text = event_data.get('original_text', '')
|
|
confidence = event_data.get('confidence', 0.0)
|
|
match_type = event_data.get('match_type', 'unknown')
|
|
|
|
print(f"⚙️ 命令处理: '{command_text}' (原始: '{original_text}', 匹配: {match_type}, 置信度: {confidence:.2f})")
|
|
except Exception as e:
|
|
print(f"✗ 命令处理事件处理失败: {e}") |