example_usage.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. """
  2. Example usage of the Trixy Event System.
  3. This file demonstrates how to use the event system in practice,
  4. including defining event handlers, registering components, and
  5. triggering events. It also serves as a test of the implementation.
  6. """
  7. import time
  8. from datetime import datetime
  9. from typing import Any
  10. import sys
  11. import os
  12. sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
  13. from trixy_core.events import (
  14. EventHandler, TrixyEvent, EventType,
  15. SatelliteInfo, SpeakerInfo,
  16. WakewordReceivedEventData, TextReceivedEventData,
  17. SystemStartupEventData, PluginLoadedEventData
  18. )
  19. class ExamplePlugin:
  20. """Example plugin demonstrating event handling."""
  21. def __init__(self, name: str):
  22. self.name = name
  23. self.wakeword_count = 0
  24. self.text_count = 0
  25. @TrixyEvent(["wakeword_received", "text_received"], priority=10)
  26. def handle_voice_events(self, event_name: str, event_data: Any):
  27. """Handle voice-related events with high priority."""
  28. if event_name == "wakeword_received":
  29. self.wakeword_count += 1
  30. speaker_name = event_data.speaker_info.speaker_name
  31. satellite_room = event_data.satellite_info.room_id
  32. print(f"[{self.name}] Wakeword from {speaker_name} in {satellite_room} "
  33. f"(total: {self.wakeword_count})")
  34. elif event_name == "text_received":
  35. self.text_count += 1
  36. text = event_data.text
  37. confidence = event_data.confidence
  38. print(f"[{self.name}] Text: '{text}' (confidence: {confidence:.2f}) "
  39. f"(total: {self.text_count})")
  40. @TrixyEvent("system_startup", priority=5)
  41. def on_startup(self, event_name: str, event_data: SystemStartupEventData):
  42. """Handle system startup."""
  43. print(f"[{self.name}] System started in {event_data.mode} mode, "
  44. f"version {event_data.version}")
  45. @TrixyEvent(["plugin_loaded", "plugin_unloaded"])
  46. def on_plugin_events(self, event_name: str, event_data: Any):
  47. """Handle plugin events."""
  48. plugin_name = event_data.plugin_name
  49. if event_name == "plugin_loaded":
  50. print(f"[{self.name}] Plugin '{plugin_name}' was loaded")
  51. else:
  52. print(f"[{self.name}] Plugin '{plugin_name}' was unloaded")
  53. class ExampleSatelliteManager:
  54. """Example satellite manager component."""
  55. def __init__(self):
  56. self.connected_satellites = {}
  57. @TrixyEvent(["satellite_connected", "satellite_disconnected"], priority=20)
  58. def manage_satellites(self, event_name: str, event_data: Any):
  59. """Manage satellite connections."""
  60. satellite_info = event_data.satellite_info
  61. satellite_id = satellite_info.satellite_id
  62. if event_name == "satellite_connected":
  63. self.connected_satellites[satellite_id] = satellite_info
  64. print(f"[SatelliteManager] Connected: {satellite_info.alias} "
  65. f"in {satellite_info.room_id} ({len(self.connected_satellites)} total)")
  66. elif event_name == "satellite_disconnected":
  67. if satellite_id in self.connected_satellites:
  68. del self.connected_satellites[satellite_id]
  69. print(f"[SatelliteManager] Disconnected: {satellite_id} "
  70. f"({len(self.connected_satellites)} remaining)")
  71. def demonstrate_event_system():
  72. """Demonstrate the complete event system functionality."""
  73. print("=== Trixy Event System Demonstration ===\n")
  74. # Create event handler
  75. print("1. Creating EventHandler...")
  76. event_handler = EventHandler(max_history_size=50)
  77. event_handler.enable_debug_mode(True)
  78. # Create example components
  79. print("\n2. Creating components...")
  80. voice_plugin = ExamplePlugin("VoicePlugin")
  81. nlp_plugin = ExamplePlugin("NLPPlugin")
  82. satellite_manager = ExampleSatelliteManager()
  83. # Register components
  84. print("\n3. Registering event handlers...")
  85. event_handler.register_handler_object(voice_plugin)
  86. event_handler.register_handler_object(nlp_plugin)
  87. event_handler.register_handler_object(satellite_manager)
  88. # Display registered handlers
  89. print("\n4. Registered handlers:")
  90. handlers = event_handler.get_registered_handlers()
  91. for event_type, handler_list in handlers.items():
  92. print(f" {event_type}: {', '.join(handler_list)}")
  93. print("\n5. Triggering events...\n")
  94. # Trigger system startup
  95. print("--- System Startup ---")
  96. event_handler.trigger_event(
  97. EventType.SYSTEM_STARTUP,
  98. mode="server",
  99. version="1.0.0",
  100. config_file="server_config.json",
  101. debug_mode=True
  102. )
  103. # Create sample satellite and speaker info
  104. satellite_info = SatelliteInfo(
  105. satellite_id="sat_001",
  106. mac_address="AA:BB:CC:DD:EE:FF",
  107. room_id="kitchen",
  108. alias="Kitchen Speaker",
  109. version="1.0.0",
  110. audio_ports={"input": 2102, "output": 2103}
  111. )
  112. speaker_info = SpeakerInfo(
  113. speaker_id="spk_001",
  114. speaker_name="Alice",
  115. confidence=0.95
  116. )
  117. time.sleep(0.1) # Small delay for readability
  118. # Trigger satellite connection
  119. print("\n--- Satellite Connection ---")
  120. event_handler.trigger_event(
  121. EventType.SATELLITE_CONNECTED,
  122. satellite_info=satellite_info,
  123. server_assigned_ports={"input": 2102, "output": 2103, "music": 2104}
  124. )
  125. time.sleep(0.1)
  126. # Trigger wakeword detection
  127. print("\n--- Wakeword Detection ---")
  128. event_handler.trigger_event(
  129. EventType.WAKEWORD_RECEIVED,
  130. wakeword_id="trixy",
  131. speaker_info=speaker_info,
  132. satellite_info=satellite_info,
  133. volume=0.8,
  134. confidence=0.92
  135. )
  136. time.sleep(0.1)
  137. # Trigger text processing
  138. print("\n--- Text Processing ---")
  139. event_handler.trigger_event(
  140. EventType.TEXT_RECEIVED,
  141. conversation_id="conv_001",
  142. text="What's the weather like today?",
  143. confidence=0.89,
  144. speaker_info=speaker_info,
  145. satellite_info=satellite_info
  146. )
  147. time.sleep(0.1)
  148. # Trigger plugin events
  149. print("\n--- Plugin Events ---")
  150. event_handler.trigger_event(
  151. EventType.PLUGIN_LOADED,
  152. plugin_name="weather_plugin",
  153. plugin_path="/plugins/weather_plugin",
  154. plugin_version="2.1.0",
  155. load_time_ms=150.5
  156. )
  157. time.sleep(0.1)
  158. # Trigger more events to show statistics
  159. print("\n--- Additional Events for Statistics ---")
  160. for i in range(3):
  161. event_handler.trigger_event(
  162. EventType.WAKEWORD_RECEIVED,
  163. wakeword_id="trixy",
  164. speaker_info=speaker_info,
  165. satellite_info=satellite_info,
  166. volume=0.7 + i * 0.1,
  167. confidence=0.85 + i * 0.05
  168. )
  169. # Show event statistics
  170. print("\n6. Event Statistics:")
  171. stats = event_handler.get_event_statistics()
  172. for event_type, type_stats in stats.items():
  173. print(f" {event_type}:")
  174. print(f" Triggered: {type_stats['triggered']}")
  175. print(f" Completed: {type_stats['completed']}")
  176. print(f" Failed: {type_stats['failed']}")
  177. print(f" Success Rate: {type_stats['success_rate_percent']}%")
  178. print(f" Avg Execution Time: {type_stats['avg_execution_time_ms']:.2f}ms")
  179. print(f" Handlers: {type_stats['handlers_registered']}")
  180. # Show recent event history
  181. print("\n7. Recent Event History:")
  182. history = event_handler.get_event_history(limit=5)
  183. for entry in history:
  184. print(f" {entry.timestamp.strftime('%H:%M:%S.%f')[:-3]} - "
  185. f"{entry.event_type} - {entry.status.value} - "
  186. f"{entry.execution_time_ms:.1f}ms")
  187. # Test async events
  188. print("\n8. Testing Async Events...")
  189. async_event_ids = []
  190. for i in range(3):
  191. event_id = event_handler.trigger_event_async(
  192. EventType.TEXT_RECEIVED,
  193. conversation_id=f"async_conv_{i}",
  194. text=f"Async message {i + 1}",
  195. confidence=0.9,
  196. speaker_info=speaker_info
  197. )
  198. async_event_ids.append(event_id)
  199. # Wait for async events to complete
  200. print(" Waiting for async events to complete...")
  201. for event_id in async_event_ids:
  202. result = event_handler.wait_for_event(event_id, timeout=5.0)
  203. if result:
  204. print(f" Async event {event_id} completed in {result.execution_time_ms:.1f}ms")
  205. else:
  206. print(f" Async event {event_id} timed out")
  207. # Test event filtering
  208. print("\n9. Testing Event Filtering...")
  209. print(" Disabling wakeword_received events...")
  210. event_handler.disable_event_type("wakeword_received")
  211. # This should be ignored
  212. event_handler.trigger_event(
  213. EventType.WAKEWORD_RECEIVED,
  214. wakeword_id="trixy",
  215. speaker_info=speaker_info,
  216. satellite_info=satellite_info,
  217. volume=0.5
  218. )
  219. print(" Re-enabling wakeword_received events...")
  220. event_handler.enable_event_type("wakeword_received")
  221. # This should work
  222. event_handler.trigger_event(
  223. EventType.WAKEWORD_RECEIVED,
  224. wakeword_id="trixy",
  225. speaker_info=speaker_info,
  226. satellite_info=satellite_info,
  227. volume=0.9
  228. )
  229. # Final statistics
  230. print("\n10. Final Statistics:")
  231. final_stats = event_handler.get_event_statistics()
  232. for event_type, type_stats in final_stats.items():
  233. print(f" {event_type}: {type_stats['triggered']} triggered, "
  234. f"{type_stats['completed']} completed")
  235. # Cleanup
  236. print("\n11. Shutting down event handler...")
  237. event_handler.shutdown()
  238. print("\n=== Demonstration Complete ===")
  239. if __name__ == "__main__":
  240. demonstrate_event_system()