fix: Modus-Wechsel via App/ID funktioniert jetzt

Bug: App ModeSelector sendet rvs.send('mode', { mode: 'normal' })
mit ID, Bridge's detect_mode_switch() sucht aber nach Aktivierungs-
phrasen wie 'aria, normal-modus' → kein Match → Modus-Wechsel
wurde ignoriert, TTS-Verhalten blieb auf NORMAL haengen.

Fix:
- modes.py: mode_from_id() mappt IDs zu Mode-Enum
  ('normal', 'dnd', 'nicht_stoeren', 'fluester', 'whisper',
   'hangar', 'gaming' — flexibel)
- aria_bridge.py: mode-Handler versucht erst ID-Mapping, dann
  Phrasen-Erkennung als Fallback
- Unbekannte Modi werden geloggt
- Bestaetigung wird an alle Clients zurueckgesendet damit App-UI
  synchron bleibt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck 2026-04-19 22:51:18 +02:00
parent 99cb83202e
commit 47fe4ad655
2 changed files with 29 additions and 3 deletions

View File

@ -37,7 +37,7 @@ import websockets
from faster_whisper import WhisperModel
from openwakeword.model import Model as WakeWordModel
from modes import Mode, detect_mode_switch, should_speak
from modes import Mode, detect_mode_switch, mode_from_id, should_speak
# ── Logging ──────────────────────────────────────────────────
@ -1167,9 +1167,9 @@ class ARIABridge:
return
elif msg_type == "mode":
# Moduswechsel von der App
# Moduswechsel von der App — ID ('normal', 'dnd', ...) ODER Aktivierungsphrase
mode_name = payload.get("mode", "")
new_mode = detect_mode_switch(mode_name)
new_mode = mode_from_id(mode_name) or detect_mode_switch(mode_name)
if new_mode is not None:
self.current_mode = new_mode
logger.info(
@ -1177,6 +1177,14 @@ class ARIABridge:
self.current_mode.config.emoji,
self.current_mode.config.name,
)
# Bestaetigung an alle Clients (App/Diagnostic) damit UI sync bleibt
await self._send_to_rvs({
"type": "mode",
"payload": {"mode": mode_name, "name": self.current_mode.config.name},
"timestamp": int(asyncio.get_event_loop().time() * 1000),
})
else:
logger.warning("[rvs] Unbekannter Modus: '%s'", mode_name)
elif msg_type == "location":
# GPS-Daten von der App

View File

@ -91,6 +91,24 @@ _ACTIVATION_MAP: dict[str, Mode] = {
mode.config.activation_phrase.lower(): mode for mode in Mode
}
# ID-Mapping fuer API-Mode-Wechsel (z.B. App ModeSelector schickt 'normal')
_ID_MAP: dict[str, Mode] = {
"normal": Mode.NORMAL,
"nicht_stoeren": Mode.DND,
"dnd": Mode.DND,
"fluester": Mode.WHISPER,
"whisper": Mode.WHISPER,
"hangar": Mode.HANGAR,
"gaming": Mode.GAMING,
}
def mode_from_id(mode_id: str) -> Optional[Mode]:
"""ID-basiertes Mapping fuer API-Mode-Wechsel (ohne Aktivierungsphrase)."""
if not mode_id:
return None
return _ID_MAP.get(mode_id.strip().lower())
def detect_mode_switch(text: str) -> Optional[Mode]:
"""Erkennt ob ein Text eine Modus-Umschaltung enthaelt.