218 lines
No EOL
8.6 KiB
Python
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() |