tschunkorder/backend/websocket_manager.py
2025-07-10 22:28:17 +02:00

218 lines
No EOL
8.6 KiB
Python

from fastapi import WebSocket
from typing import List, Dict, Any
import json
import asyncio
from datetime import datetime
from models import CreateOrderRequest, Drink
class WebSocketManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
self.db = None # Wird später gesetzt
def set_database(self, database):
"""Setzt die Datenbank-Referenz (Dependency Injection)."""
self.db = database
async def connect(self, websocket: WebSocket):
"""Neue WebSocket-Verbindung hinzufügen."""
await websocket.accept()
self.active_connections.append(websocket)
print(f"WebSocket verbunden. Aktive Verbindungen: {len(self.active_connections)}")
def disconnect(self, websocket: WebSocket):
"""WebSocket-Verbindung entfernen."""
if websocket in self.active_connections:
self.active_connections.remove(websocket)
print(f"WebSocket getrennt. Aktive Verbindungen: {len(self.active_connections)}")
async def broadcast(self, message: Dict[str, Any]):
"""Nachricht an alle verbundenen Clients senden."""
if not self.active_connections:
return
# Nachricht als JSON serialisieren
message_json = json.dumps(message, default=str)
# An alle verbundenen Clients senden
disconnected = []
for connection in self.active_connections:
try:
await connection.send_text(message_json)
except Exception as e:
print(f"Fehler beim Senden an WebSocket: {e}")
disconnected.append(connection)
# Getrennte Verbindungen entfernen
for connection in disconnected:
self.disconnect(connection)
async def send_to_client(self, websocket: WebSocket, message: Dict[str, Any]):
"""Nachricht an einen spezifischen Client senden."""
try:
message_json = json.dumps(message, default=str)
await websocket.send_text(message_json)
except Exception as e:
print(f"Fehler beim Senden an WebSocket: {e}")
self.disconnect(websocket)
async def handle_create_order(self, websocket: WebSocket, data: Dict[str, Any]):
"""Behandelt eine Bestellungsanfrage über WebSocket."""
try:
# Validierung der Anfrage
if "drinks" not in data or not data["drinks"]:
await self.send_to_client(websocket, {
"type": "order_created_response",
"success": False,
"error": "Mindestens ein Getränk muss bestellt werden",
"timestamp": datetime.now().isoformat()
})
return
# Drinks aus der Anfrage erstellen
drinks = []
for drink_data in data["drinks"]:
drink = Drink(
drink_type=drink_data["drink_type"],
mate_type=drink_data["mate_type"],
quantity=drink_data["quantity"],
notes=drink_data.get("notes", "")
)
drinks.append(drink)
# Bestellung in der Datenbank erstellen
if self.db:
order = await self.db.create_order(drinks)
# Erfolgsantwort an den Client senden
await self.send_to_client(websocket, {
"type": "order_created_response",
"success": True,
"order": order.model_dump(),
"timestamp": datetime.now().isoformat()
})
else:
await self.send_to_client(websocket, {
"type": "order_created_response",
"success": False,
"error": "Datenbank nicht verfügbar",
"timestamp": datetime.now().isoformat()
})
except Exception as e:
print(f"Fehler beim Erstellen der Bestellung über WebSocket: {e}")
await self.send_to_client(websocket, {
"type": "order_created_response",
"success": False,
"error": f"Fehler beim Erstellen der Bestellung: {str(e)}",
"timestamp": datetime.now().isoformat()
})
async def handle_get_all_orders(self, websocket: WebSocket):
"""Sendet alle Bestellungen an den anfragenden Client."""
try:
if self.db:
orders = self.db.get_all_orders()
await self.send_to_client(websocket, {
"type": "all_orders",
"orders": [order.model_dump() for order in orders],
"timestamp": datetime.now().isoformat()
})
else:
await self.send_to_client(websocket, {
"type": "all_orders",
"orders": [],
"error": "Datenbank nicht verfügbar",
"timestamp": datetime.now().isoformat()
})
except Exception as e:
print(f"Fehler beim Abrufen aller Bestellungen: {e}")
await self.send_to_client(websocket, {
"type": "all_orders",
"orders": [],
"error": f"Fehler beim Abrufen der Bestellungen: {str(e)}",
"timestamp": datetime.now().isoformat()
})
async def handle_delete_order(self, websocket: WebSocket, data: Dict[str, Any]):
"""Behandelt eine Bestelllöschung über WebSocket."""
try:
# Validierung der Anfrage
if "order_id" not in data or not data["order_id"]:
await self.send_to_client(websocket, {
"type": "order_deleted_response",
"success": False,
"error": "Order ID ist erforderlich",
"timestamp": datetime.now().isoformat()
})
return
order_id = data["order_id"]
# Bestellung in der Datenbank löschen
if self.db:
success = await self.db.delete_order(order_id)
if success:
# Erfolgsantwort an den Client senden
await self.send_to_client(websocket, {
"type": "order_deleted_response",
"success": True,
"message": f"Bestellung {order_id} wurde erfolgreich gelöscht",
"timestamp": datetime.now().isoformat()
})
else:
await self.send_to_client(websocket, {
"type": "order_deleted_response",
"success": False,
"error": "Bestellung nicht gefunden",
"timestamp": datetime.now().isoformat()
})
else:
await self.send_to_client(websocket, {
"type": "order_deleted_response",
"success": False,
"error": "Datenbank nicht verfügbar",
"timestamp": datetime.now().isoformat()
})
except Exception as e:
print(f"Fehler beim Löschen der Bestellung über WebSocket: {e}")
await self.send_to_client(websocket, {
"type": "order_deleted_response",
"success": False,
"error": f"Fehler beim Löschen der Bestellung: {str(e)}",
"timestamp": datetime.now().isoformat()
})
async def broadcast_order_created(self, order: Dict[str, Any]):
"""Broadcast für neue Bestellung."""
message = {
"type": "order_created",
"timestamp": datetime.now().isoformat(),
"order": order
}
await self.broadcast(message)
async def broadcast_order_deleted(self, order_id: str):
"""Broadcast für gelöschte Bestellung."""
message = {
"type": "order_deleted",
"timestamp": datetime.now().isoformat(),
"order_id": order_id
}
await self.broadcast(message)
async def broadcast_all_orders(self, orders: List[Dict[str, Any]]):
"""Broadcast für alle Bestellungen (z.B. bei initialer Verbindung)."""
message = {
"type": "all_orders",
"timestamp": datetime.now().isoformat(),
"orders": orders
}
await self.broadcast(message)
# Globale WebSocket-Manager-Instanz
websocket_manager = WebSocketManager()