|
@@ -401,42 +401,66 @@ class IntentDispatcherService(IService):
|
|
|
Verarbeitet TTS-Ergebnis:
|
|
Verarbeitet TTS-Ergebnis:
|
|
|
1. Audio an Satellite senden
|
|
1. Audio an Satellite senden
|
|
|
2. Bei Follow-up: followup_expected emittieren
|
|
2. Bei Follow-up: followup_expected emittieren
|
|
|
|
|
+ 3. Ohne Follow-up: ConversationEnd senden
|
|
|
"""
|
|
"""
|
|
|
# tts_completed kommt als generisches EventData (via emit() mit dict)
|
|
# tts_completed kommt als generisches EventData (via emit() mit dict)
|
|
|
satellite_id = event_data.get("satellite_id", "")
|
|
satellite_id = event_data.get("satellite_id", "")
|
|
|
audio_data_hex = event_data.get("audio_data", "")
|
|
audio_data_hex = event_data.get("audio_data", "")
|
|
|
request_id = event_data.get("request_id", "")
|
|
request_id = event_data.get("request_id", "")
|
|
|
|
|
+ session_id = event_data.get("session_id", "")
|
|
|
|
|
|
|
|
# Audio an Satellite senden (falls satellite_id vorhanden)
|
|
# Audio an Satellite senden (falls satellite_id vorhanden)
|
|
|
if satellite_id and audio_data_hex:
|
|
if satellite_id and audio_data_hex:
|
|
|
await self._send_tts_to_satellite(satellite_id, audio_data_hex)
|
|
await self._send_tts_to_satellite(satellite_id, audio_data_hex)
|
|
|
|
|
|
|
|
# Follow-up prüfen
|
|
# Follow-up prüfen
|
|
|
- if not request_id:
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ followup_info = self._pending_followups.pop(request_id, None) if request_id else None
|
|
|
|
|
+
|
|
|
|
|
+ if followup_info:
|
|
|
|
|
+ success = event_data.get("success", True)
|
|
|
|
|
+ if not success:
|
|
|
|
|
+ perror(f"TTS fehlgeschlagen für Follow-up Request: {request_id}")
|
|
|
|
|
+ await self._send_conversation_end(satellite_id, session_id)
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ # followup_expected emittieren - Client wechselt in Hör-Modus
|
|
|
|
|
+ followup_event = FollowUpExpected(
|
|
|
|
|
+ satellite_id=followup_info["satellite_id"],
|
|
|
|
|
+ session_id=followup_info["session_id"],
|
|
|
|
|
+ room_id=followup_info["room_id"],
|
|
|
|
|
+ timeout_seconds=30.0,
|
|
|
|
|
+ followup_context={
|
|
|
|
|
+ "previous_intent": followup_info["intent"],
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- followup_info = self._pending_followups.pop(request_id, None)
|
|
|
|
|
- if not followup_info:
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ pinfo(f"Follow-up erwartet für Satellite: {followup_info['satellite_id']}")
|
|
|
|
|
+ await self._application.events.trigger("followup_expected", followup_event)
|
|
|
|
|
+ else:
|
|
|
|
|
+ # Kein Follow-up → ConversationEnd senden
|
|
|
|
|
+ if satellite_id:
|
|
|
|
|
+ await self._send_conversation_end(satellite_id, session_id)
|
|
|
|
|
|
|
|
- success = event_data.get("success", True)
|
|
|
|
|
- if not success:
|
|
|
|
|
- perror(f"TTS fehlgeschlagen für Follow-up Request: {request_id}")
|
|
|
|
|
|
|
+ async def _send_conversation_end(self, satellite_id: str, session_id: str = "") -> None:
|
|
|
|
|
+ """Sendet ConversationEnd an den Satellite."""
|
|
|
|
|
+ satellites = getattr(self._application, "satellites", None)
|
|
|
|
|
+ if satellites is None:
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
- # followup_expected emittieren - Client wechselt in Hör-Modus
|
|
|
|
|
- followup_event = FollowUpExpected(
|
|
|
|
|
- satellite_id=followup_info["satellite_id"],
|
|
|
|
|
- session_id=followup_info["session_id"],
|
|
|
|
|
- room_id=followup_info["room_id"],
|
|
|
|
|
- timeout_seconds=30.0,
|
|
|
|
|
- followup_context={
|
|
|
|
|
- "previous_intent": followup_info["intent"],
|
|
|
|
|
- },
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ satellite = satellites.get(satellite_id)
|
|
|
|
|
+ if satellite is None or not satellite.is_connected:
|
|
|
|
|
+ return
|
|
|
|
|
|
|
|
- pinfo(f"Follow-up erwartet für Satellite: {followup_info['satellite_id']}")
|
|
|
|
|
- await self._application.events.trigger("followup_expected", followup_event)
|
|
|
|
|
|
|
+ try:
|
|
|
|
|
+ from trixy_core.network.cmd.wakeword import ConversationEnd
|
|
|
|
|
+ cmd = ConversationEnd(
|
|
|
|
|
+ session_id=session_id,
|
|
|
|
|
+ reason="completed",
|
|
|
|
|
+ )
|
|
|
|
|
+ await satellite.send_command(cmd)
|
|
|
|
|
+ pdebug(f"ConversationEnd gesendet an {satellite_id} (reason=completed)")
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ perror(f"Fehler beim Senden von ConversationEnd: {e}")
|
|
|
|
|
|
|
|
async def _send_tts_to_satellite(self, satellite_id: str, audio_data_hex: str) -> None:
|
|
async def _send_tts_to_satellite(self, satellite_id: str, audio_data_hex: str) -> None:
|
|
|
"""Sendet TTS-Audio an den Satellite."""
|
|
"""Sendet TTS-Audio an den Satellite."""
|