Files
xiaozhi-esp32-server/main/xiaozhi-server/test/wakeword_runtime/bridge/event_bridge.py
T

98 lines
2.7 KiB
Python

import json
import logging
import queue
import threading
import time
from typing import Any
logger = logging.getLogger(__name__)
class WakewordEventBridge:
def __init__(self) -> None:
self._clients: list[queue.Queue[str]] = []
self._clients_lock = threading.Lock()
self._running = True
@property
def is_running(self) -> bool:
return self._running
def build_ready_message(self) -> str:
return json.dumps(
{
"type": "bridge_connected",
"payload": {"status": "ready"},
},
ensure_ascii=False,
)
def publish_detected(self, wake_word: str) -> None:
self.publish(
"wake_word_detected",
{
"wake_word": wake_word,
"timestamp": time.time(),
},
)
def publish(self, event_type: str, payload: dict[str, Any] | None = None) -> None:
if not self._running:
return
message = json.dumps(
{
"type": event_type,
"payload": payload or {},
},
ensure_ascii=False,
)
with self._clients_lock:
clients = list(self._clients)
stale_clients: list[queue.Queue[str]] = []
for client_queue in clients:
try:
client_queue.put_nowait(message)
except queue.Full:
stale_clients.append(client_queue)
if stale_clients:
with self._clients_lock:
for client_queue in stale_clients:
if client_queue in self._clients:
self._clients.remove(client_queue)
def add_client(self) -> queue.Queue[str]:
client_queue: queue.Queue[str] = queue.Queue(maxsize=16)
with self._clients_lock:
self._clients.append(client_queue)
return client_queue
def remove_client(self, client_queue: queue.Queue[str]) -> None:
with self._clients_lock:
if client_queue in self._clients:
self._clients.remove(client_queue)
def publish_service_ready(self) -> None:
self.publish("service_ready", {"status": "ready"})
def publish_service_stopping(self) -> None:
self.publish("service_stopping", {"status": "stopping"})
def close(self) -> None:
if not self._running:
return
self.publish_service_stopping()
self._running = False
with self._clients_lock:
clients = list(self._clients)
self._clients.clear()
for client_queue in clients:
try:
client_queue.put_nowait("__bridge_closed__")
except queue.Full:
pass