small layout changes, refractoring
This commit is contained in:
61
api_client.py
Normal file
61
api_client.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
"""
|
||||||
|
API client functions for interacting with the Airport Announcement System backend.
|
||||||
|
"""
|
||||||
|
import requests
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
API_BASE_URL = "http://localhost:7999"
|
||||||
|
|
||||||
|
def get_groups() -> List[dict]:
|
||||||
|
"""Get all endpoint groups."""
|
||||||
|
response = requests.get(f"{API_BASE_URL}/groups")
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_group(group_id: int) -> Optional[dict]:
|
||||||
|
"""Get a specific endpoint group by ID."""
|
||||||
|
response = requests.get(f"{API_BASE_URL}/groups/{group_id}")
|
||||||
|
if response.status_code == 404:
|
||||||
|
return None
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def create_group(group: dict) -> dict:
|
||||||
|
"""Create a new endpoint group."""
|
||||||
|
response = requests.post(f"{API_BASE_URL}/groups", json=group)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def update_group(group_id: int, updated_group: dict) -> dict:
|
||||||
|
"""Update an existing endpoint group."""
|
||||||
|
response = requests.put(f"{API_BASE_URL}/groups/{group_id}", json=updated_group)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def delete_group(group_id: int) -> None:
|
||||||
|
"""Delete an endpoint group."""
|
||||||
|
response = requests.delete(f"{API_BASE_URL}/groups/{group_id}")
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
def start_announcement(text: str, group_id: int) -> None:
|
||||||
|
"""Start a new announcement."""
|
||||||
|
response = requests.post(f"{API_BASE_URL}/announcements", params={"text": text, "group_id": group_id})
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
def get_announcement_status() -> dict:
|
||||||
|
"""Get the status of the current announcement."""
|
||||||
|
response = requests.get(f"{API_BASE_URL}/announcements/status")
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_available_endpoints() -> List[str]:
|
||||||
|
"""Get all available endpoints."""
|
||||||
|
response = requests.get(f"{API_BASE_URL}/endpoints")
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_available_languages() -> List[str]:
|
||||||
|
"""Get all available languages for announcements."""
|
||||||
|
response = requests.get(f"{API_BASE_URL}/languages")
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
35
api_models.py
Normal file
35
api_models.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
"""
|
||||||
|
API models for the Airport Announcement System.
|
||||||
|
"""
|
||||||
|
from enum import Enum
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
class AnnouncementStates(Enum):
|
||||||
|
IDLE: str = "Ready"
|
||||||
|
TRANSLATING: str = "Translating"
|
||||||
|
GENERATING_VOICE: str = "Generating voice synthesis"
|
||||||
|
ROUTING: str = "Routing to endpoints"
|
||||||
|
ACTIVE: str = "Broadcasting announcement"
|
||||||
|
COMPLETE: str = "Complete"
|
||||||
|
ERROR: str = "Error"
|
||||||
|
|
||||||
|
class AnnouncementParameters(BaseModel):
|
||||||
|
text: Optional[str] = None
|
||||||
|
languages: List[str] = []
|
||||||
|
start_time: Optional[float] = None
|
||||||
|
|
||||||
|
class AnnouncementProgress(BaseModel):
|
||||||
|
current_state: str = AnnouncementStates.IDLE.value
|
||||||
|
progress: float = Field(default=0.0, ge=0.0, le=1.0)
|
||||||
|
error: Optional[str] = None
|
||||||
|
|
||||||
|
class EndpointGroup(BaseModel):
|
||||||
|
id: int
|
||||||
|
name: str
|
||||||
|
endpoints: List[str]
|
||||||
|
languages: List[str]
|
||||||
|
|
||||||
|
# Announcement parameters and progress as nested models
|
||||||
|
parameters: AnnouncementParameters = Field(default_factory=AnnouncementParameters)
|
||||||
|
progress: AnnouncementProgress = Field(default_factory=AnnouncementProgress)
|
||||||
@@ -3,58 +3,9 @@ import streamlit as st
|
|||||||
# Page setup must be first
|
# Page setup must be first
|
||||||
st.set_page_config(page_title="Airport Announcement System", page_icon="✈️")
|
st.set_page_config(page_title="Airport Announcement System", page_icon="✈️")
|
||||||
|
|
||||||
import requests
|
|
||||||
import time
|
import time
|
||||||
from typing import List, Optional
|
import requests
|
||||||
|
import api_client
|
||||||
API_BASE_URL = "http://localhost:7999"
|
|
||||||
|
|
||||||
class APIClient:
|
|
||||||
def get_groups(self) -> List[dict]:
|
|
||||||
response = requests.get(f"{API_BASE_URL}/groups")
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def get_group(self, group_id: int) -> Optional[dict]:
|
|
||||||
response = requests.get(f"{API_BASE_URL}/groups/{group_id}")
|
|
||||||
if response.status_code == 404:
|
|
||||||
return None
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def create_group(self, group: dict) -> dict:
|
|
||||||
response = requests.post(f"{API_BASE_URL}/groups", json=group)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def update_group(self, group_id: int, updated_group: dict) -> dict:
|
|
||||||
response = requests.put(f"{API_BASE_URL}/groups/{group_id}", json=updated_group)
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def delete_group(self, group_id: int) -> None:
|
|
||||||
response = requests.delete(f"{API_BASE_URL}/groups/{group_id}")
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
def start_announcement(self, text: str, group_id: int) -> None:
|
|
||||||
response = requests.post(f"{API_BASE_URL}/announcements", params={"text": text, "group_id": group_id})
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
def get_announcement_status(self) -> dict:
|
|
||||||
response = requests.get(f"{API_BASE_URL}/announcements/status")
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def get_available_endpoints(self) -> List[str]:
|
|
||||||
response = requests.get(f"{API_BASE_URL}/endpoints")
|
|
||||||
response.raise_for_status()
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
api_client = APIClient()
|
|
||||||
|
|
||||||
# Configuration defaults
|
|
||||||
DEFAULT_LANGUAGES = ["German", "English"]
|
|
||||||
OPTIONAL_LANGUAGES = ["French", "Spanish"]
|
|
||||||
|
|
||||||
# Initialize session state for configuration
|
# Initialize session state for configuration
|
||||||
if "endpoint_groups" not in st.session_state:
|
if "endpoint_groups" not in st.session_state:
|
||||||
@@ -64,6 +15,14 @@ if "endpoint_groups" not in st.session_state:
|
|||||||
st.error(f"Failed to load endpoint groups: {str(e)}")
|
st.error(f"Failed to load endpoint groups: {str(e)}")
|
||||||
st.session_state.endpoint_groups = []
|
st.session_state.endpoint_groups = []
|
||||||
|
|
||||||
|
# Initialize session state for available languages
|
||||||
|
if "available_languages" not in st.session_state:
|
||||||
|
try:
|
||||||
|
st.session_state.available_languages = api_client.get_available_languages()
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
st.error(f"Failed to load available languages: {str(e)}")
|
||||||
|
st.session_state.available_languages = ["German", "English"] # Fallback languages
|
||||||
|
|
||||||
# Initialize session state for announcement text and status tracking
|
# Initialize session state for announcement text and status tracking
|
||||||
if "announcement_text" not in st.session_state:
|
if "announcement_text" not in st.session_state:
|
||||||
st.session_state.announcement_text = "Hallo Welt."
|
st.session_state.announcement_text = "Hallo Welt."
|
||||||
@@ -178,8 +137,8 @@ with st.container():
|
|||||||
st.error(f"Failed to start announcement: {str(e)}")
|
st.error(f"Failed to start announcement: {str(e)}")
|
||||||
|
|
||||||
# Display success message if flag is set
|
# Display success message if flag is set
|
||||||
if st.session_state.show_success_message:
|
#if st.session_state.show_success_message:
|
||||||
st.success("Announcement started successfully")
|
# st.success("Announcement started successfully")
|
||||||
|
|
||||||
# Configuration section in sidebar
|
# Configuration section in sidebar
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
@@ -263,7 +222,7 @@ with st.sidebar:
|
|||||||
|
|
||||||
selected_languages = st.multiselect(
|
selected_languages = st.multiselect(
|
||||||
f"Languages {i+1}",
|
f"Languages {i+1}",
|
||||||
options=DEFAULT_LANGUAGES + OPTIONAL_LANGUAGES,
|
options=st.session_state.available_languages,
|
||||||
default=group["languages"],
|
default=group["languages"],
|
||||||
key=languages_key
|
key=languages_key
|
||||||
)
|
)
|
||||||
@@ -283,11 +242,13 @@ with st.sidebar:
|
|||||||
if st.button("➕ Add Group"):
|
if st.button("➕ Add Group"):
|
||||||
try:
|
try:
|
||||||
new_id = max(g["id"] for g in st.session_state.endpoint_groups) + 1 if st.session_state.endpoint_groups else 1
|
new_id = max(g["id"] for g in st.session_state.endpoint_groups) + 1 if st.session_state.endpoint_groups else 1
|
||||||
|
# Get the default languages from the backend (first two languages)
|
||||||
|
default_languages = st.session_state.available_languages[:2] if len(st.session_state.available_languages) >= 2 else st.session_state.available_languages
|
||||||
new_group = {
|
new_group = {
|
||||||
"id": new_id,
|
"id": new_id,
|
||||||
"name": f"Group {len(st.session_state.endpoint_groups)+1}",
|
"name": f"Group {len(st.session_state.endpoint_groups)+1}",
|
||||||
"endpoints": [],
|
"endpoints": [],
|
||||||
"languages": DEFAULT_LANGUAGES.copy()
|
"languages": default_languages
|
||||||
}
|
}
|
||||||
created_group = api_client.create_group(new_group)
|
created_group = api_client.create_group(new_group)
|
||||||
st.session_state.endpoint_groups.append(created_group)
|
st.session_state.endpoint_groups.append(created_group)
|
||||||
|
|||||||
26
main_mock.py
26
main_mock.py
@@ -6,8 +6,18 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
def stream_output(process, prefix):
|
||||||
|
"""Stream the output of a process to the console in real-time."""
|
||||||
|
for line in iter(process.stdout.readline, ''):
|
||||||
|
if line:
|
||||||
|
print(f"{prefix}: {line.strip()}")
|
||||||
|
for line in iter(process.stderr.readline, ''):
|
||||||
|
if line:
|
||||||
|
print(f"{prefix} ERROR: {line.strip()}")
|
||||||
|
|
||||||
def start_backend():
|
def start_backend():
|
||||||
"""Start the backend API server."""
|
"""Start the backend API server."""
|
||||||
print("Starting backend API server...")
|
print("Starting backend API server...")
|
||||||
@@ -15,8 +25,14 @@ def start_backend():
|
|||||||
[sys.executable, "-m", "uvicorn", "mock_backend.mock_api:app", "--host", "0.0.0.0", "--port", "7999", "--reload"],
|
[sys.executable, "-m", "uvicorn", "mock_backend.mock_api:app", "--host", "0.0.0.0", "--port", "7999", "--reload"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
text=True
|
text=True,
|
||||||
|
bufsize=1 # Line buffered
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Start a thread to stream the backend output
|
||||||
|
backend_thread = threading.Thread(target=stream_output, args=(backend_process, "BACKEND"), daemon=True)
|
||||||
|
backend_thread.start()
|
||||||
|
|
||||||
# Wait a moment to ensure the backend has started
|
# Wait a moment to ensure the backend has started
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
return backend_process
|
return backend_process
|
||||||
@@ -28,8 +44,14 @@ def start_frontend():
|
|||||||
[sys.executable, "-m", "streamlit", "run", "auracaster-webui.py"],
|
[sys.executable, "-m", "streamlit", "run", "auracaster-webui.py"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
text=True
|
text=True,
|
||||||
|
bufsize=1 # Line buffered
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Start a thread to stream the frontend output
|
||||||
|
frontend_thread = threading.Thread(target=stream_output, args=(frontend_process, "FRONTEND"), daemon=True)
|
||||||
|
frontend_thread.start()
|
||||||
|
|
||||||
return frontend_process
|
return frontend_process
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from fastapi import FastAPI, HTTPException
|
from fastapi import FastAPI, HTTPException
|
||||||
from mock_backend.mock_backend import announcement_system, EndpointGroup
|
from mock_backend.mock_backend import announcement_system
|
||||||
|
from api_models import EndpointGroup
|
||||||
from typing import List
|
from typing import List
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
@@ -45,22 +46,15 @@ def start_announcement(text: str, group_id: int):
|
|||||||
|
|
||||||
@app.get("/announcements/status")
|
@app.get("/announcements/status")
|
||||||
def get_announcement_status():
|
def get_announcement_status():
|
||||||
process = announcement_system.current_process
|
return announcement_system.get_announcement_status()
|
||||||
return {
|
|
||||||
"state": process.current_state.value,
|
|
||||||
"progress": process.progress,
|
|
||||||
"error": process.error,
|
|
||||||
"details": {
|
|
||||||
"text": process.details.text,
|
|
||||||
"languages": process.details.languages,
|
|
||||||
"group": process.details.group,
|
|
||||||
"start_time": process.details.start_time
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@app.get("/endpoints")
|
@app.get("/endpoints")
|
||||||
def get_available_endpoints():
|
def get_available_endpoints():
|
||||||
return announcement_system.available_endpoints
|
return announcement_system.get_available_endpoints()
|
||||||
|
|
||||||
|
@app.get("/languages")
|
||||||
|
def get_available_languages():
|
||||||
|
return announcement_system.get_available_languages()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn.run('mock_backend.mock_api:app', host="0.0.0.0", port=7999, reload=True)
|
uvicorn.run('mock_backend.mock_api:app', host="0.0.0.0", port=7999, reload=True)
|
||||||
|
|||||||
@@ -1,42 +1,16 @@
|
|||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
from enum import Enum
|
|
||||||
from pydantic import BaseModel, Field
|
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
ENDPOINTS = [f"endpoint{i}" for i in range(1, 4)] # Predefined endpoints
|
from api_models import EndpointGroup, AnnouncementStates
|
||||||
|
|
||||||
class AnnouncementStates(Enum):
|
AVAILABLE_ENDPOINTS = [f"endpoint{i}" for i in range(1, 4)] # Predefined endpoints
|
||||||
IDLE: str = "Ready"
|
AVAILABLE_LANGUAGES = ["German", "English", "French", "Spanish", "Italian"]
|
||||||
TRANSLATING: str = "Translating"
|
|
||||||
GENERATING_VOICE: str = "Generating voice synthesis"
|
|
||||||
ROUTING: str = "Routing to endpoints"
|
|
||||||
ACTIVE: str = "Broadcasting announcement"
|
|
||||||
COMPLETE: str = "Complete"
|
|
||||||
ERROR: str = "Error"
|
|
||||||
|
|
||||||
class EndpointGroup(BaseModel):
|
|
||||||
id: int
|
|
||||||
name: str
|
|
||||||
endpoints: List[str]
|
|
||||||
languages: List[str]
|
|
||||||
|
|
||||||
class AnnouncementDetails(BaseModel):
|
|
||||||
text: str
|
|
||||||
languages: List[str]
|
|
||||||
group: EndpointGroup
|
|
||||||
start_time: float
|
|
||||||
|
|
||||||
class AnnouncementProgress(BaseModel):
|
|
||||||
current_state: str = AnnouncementStates.IDLE
|
|
||||||
error: Optional[str] = None
|
|
||||||
details: AnnouncementDetails
|
|
||||||
progress: float = Field(default=0.0, ge=0.0, le=1.0)
|
|
||||||
description: str = Field(default="Ready")
|
|
||||||
|
|
||||||
class AnnouncementSystem:
|
class AnnouncementSystem:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.available_endpoints = ENDPOINTS
|
self.available_endpoints = AVAILABLE_ENDPOINTS
|
||||||
|
self.available_languages = AVAILABLE_LANGUAGES
|
||||||
self.endpoint_groups = [
|
self.endpoint_groups = [
|
||||||
EndpointGroup(
|
EndpointGroup(
|
||||||
id=1,
|
id=1,
|
||||||
@@ -51,56 +25,69 @@ class AnnouncementSystem:
|
|||||||
languages=["German", "English"]
|
languages=["German", "English"]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.current_process = AnnouncementProgress(
|
self.active_group_id = None
|
||||||
details=AnnouncementDetails(
|
|
||||||
text="",
|
|
||||||
languages=[],
|
|
||||||
group=EndpointGroup(
|
|
||||||
id=0,
|
|
||||||
name="",
|
|
||||||
endpoints=[],
|
|
||||||
languages=[]
|
|
||||||
),
|
|
||||||
start_time=0.0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self._thread = None
|
self._thread = None
|
||||||
|
self.last_completed_group_id = None
|
||||||
|
|
||||||
|
def start_announcement(self, text: str, group: EndpointGroup):
|
||||||
|
# Find the group in our list to ensure we're working with the actual instance
|
||||||
|
target_group = self.get_endpoint_group(group.id)
|
||||||
|
if not target_group:
|
||||||
|
raise ValueError(f"Group with ID {group.id} not found")
|
||||||
|
|
||||||
def start_announcement(self, text, group):
|
# Check if this group has an announcement in progress
|
||||||
if self.current_process.current_state not in [AnnouncementStates.IDLE, AnnouncementStates.COMPLETE]:
|
if target_group.progress.current_state not in [AnnouncementStates.IDLE.value, AnnouncementStates.COMPLETE.value]:
|
||||||
raise Exception("Announcement already in progress")
|
raise Exception("Announcement already in progress for this group")
|
||||||
|
|
||||||
self.current_process.details.text = text
|
# Check if any other announcement is in progress
|
||||||
self.current_process.details.group = group
|
for g in self.endpoint_groups:
|
||||||
# Set the languages from the group
|
if g.progress.current_state not in [AnnouncementStates.IDLE.value, AnnouncementStates.COMPLETE.value]:
|
||||||
self.current_process.details.languages = group.languages
|
raise Exception("Another announcement is already in progress")
|
||||||
self._thread = threading.Thread(target=self._run_process)
|
|
||||||
|
# If this group was the last completed group, clear that reference
|
||||||
|
if self.last_completed_group_id == target_group.id:
|
||||||
|
self.last_completed_group_id = None
|
||||||
|
|
||||||
|
# Reset the group to IDLE state if it was in COMPLETE state
|
||||||
|
if target_group.progress.current_state == AnnouncementStates.COMPLETE.value:
|
||||||
|
target_group.progress.current_state = AnnouncementStates.IDLE.value
|
||||||
|
target_group.progress.progress = 0.0
|
||||||
|
|
||||||
|
# Set up the announcement parameters
|
||||||
|
target_group.parameters.text = text
|
||||||
|
target_group.parameters.languages = target_group.languages.copy()
|
||||||
|
target_group.parameters.start_time = time.time()
|
||||||
|
self.active_group_id = target_group.id
|
||||||
|
|
||||||
|
# Start the announcement process in a separate thread
|
||||||
|
self._thread = threading.Thread(target=self._run_process, args=(target_group,))
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
|
|
||||||
def _run_process(self):
|
def _run_process(self, group: EndpointGroup):
|
||||||
self.current_process.details.start_time = time.time()
|
|
||||||
try:
|
try:
|
||||||
self._update_state(AnnouncementStates.TRANSLATING)
|
self._update_state(group, AnnouncementStates.TRANSLATING)
|
||||||
time.sleep(1) # Simulate translation
|
time.sleep(1) # Simulate translation
|
||||||
|
|
||||||
self._update_state(AnnouncementStates.GENERATING_VOICE)
|
self._update_state(group, AnnouncementStates.GENERATING_VOICE)
|
||||||
time.sleep(1) # Voice synthesis
|
time.sleep(1) # Voice synthesis
|
||||||
|
|
||||||
self._update_state(AnnouncementStates.ROUTING)
|
self._update_state(group, AnnouncementStates.ROUTING)
|
||||||
time.sleep(len(self.current_process.details.group.endpoints) * 0.5)
|
time.sleep(len(group.endpoints) * 0.5)
|
||||||
|
|
||||||
self._update_state(AnnouncementStates.ACTIVE)
|
self._update_state(group, AnnouncementStates.ACTIVE)
|
||||||
time.sleep(1) # Simulate broadcast
|
time.sleep(1) # Simulate broadcast
|
||||||
|
|
||||||
self._update_state(AnnouncementStates.COMPLETE)
|
self._update_state(group, AnnouncementStates.COMPLETE)
|
||||||
|
self.last_completed_group_id = group.id
|
||||||
|
self.active_group_id = None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.current_process.error = str(e)
|
group.progress.error = str(e)
|
||||||
self._update_state(AnnouncementStates.ERROR)
|
self._update_state(group, AnnouncementStates.ERROR)
|
||||||
|
self.active_group_id = None
|
||||||
|
|
||||||
def _update_state(self, new_state):
|
def _update_state(self, group: EndpointGroup, new_state: AnnouncementStates):
|
||||||
self.current_process.current_state = new_state
|
group.progress.current_state = new_state.value
|
||||||
|
|
||||||
# Progress based on state transitions
|
# Progress based on state transitions
|
||||||
state_progress = {
|
state_progress = {
|
||||||
@@ -111,7 +98,7 @@ class AnnouncementSystem:
|
|||||||
AnnouncementStates.COMPLETE: 1.0,
|
AnnouncementStates.COMPLETE: 1.0,
|
||||||
AnnouncementStates.ERROR: 0
|
AnnouncementStates.ERROR: 0
|
||||||
}
|
}
|
||||||
self.current_process.progress = state_progress[new_state]
|
group.progress.progress = state_progress[new_state]
|
||||||
|
|
||||||
def get_endpoint_groups(self) -> List[EndpointGroup]:
|
def get_endpoint_groups(self) -> List[EndpointGroup]:
|
||||||
return self.endpoint_groups
|
return self.endpoint_groups
|
||||||
@@ -133,6 +120,7 @@ class AnnouncementSystem:
|
|||||||
if not group:
|
if not group:
|
||||||
raise ValueError(f"Group with ID {group_id} not found")
|
raise ValueError(f"Group with ID {group_id} not found")
|
||||||
|
|
||||||
|
# Update only the editable fields, not the state fields
|
||||||
group.name = updated_group.name
|
group.name = updated_group.name
|
||||||
group.endpoints = updated_group.endpoints
|
group.endpoints = updated_group.endpoints
|
||||||
group.languages = updated_group.languages
|
group.languages = updated_group.languages
|
||||||
@@ -142,7 +130,78 @@ class AnnouncementSystem:
|
|||||||
group = self.get_endpoint_group(group_id)
|
group = self.get_endpoint_group(group_id)
|
||||||
if not group:
|
if not group:
|
||||||
raise ValueError(f"Group with ID {group_id} not found")
|
raise ValueError(f"Group with ID {group_id} not found")
|
||||||
|
|
||||||
|
# Cannot delete a group with an active announcement
|
||||||
|
if group.progress.current_state not in [AnnouncementStates.IDLE.value, AnnouncementStates.COMPLETE.value]:
|
||||||
|
raise ValueError(f"Cannot delete group with an active announcement")
|
||||||
|
|
||||||
self.endpoint_groups = [g for g in self.endpoint_groups if g.id != group_id]
|
self.endpoint_groups = [g for g in self.endpoint_groups if g.id != group_id]
|
||||||
|
|
||||||
|
def get_available_languages(self) -> List[str]:
|
||||||
|
"""Get the list of available languages for announcements."""
|
||||||
|
return self.available_languages
|
||||||
|
|
||||||
|
def get_available_endpoints(self) -> List[str]:
|
||||||
|
"""Get the list of available endpoints for announcements."""
|
||||||
|
return self.available_endpoints
|
||||||
|
|
||||||
|
def get_announcement_status(self) -> dict:
|
||||||
|
"""Get the status of the current announcement."""
|
||||||
|
if self.active_group_id is not None:
|
||||||
|
active_group = self.get_endpoint_group(self.active_group_id)
|
||||||
|
return {
|
||||||
|
"state": active_group.progress.current_state,
|
||||||
|
"progress": active_group.progress.progress,
|
||||||
|
"error": active_group.progress.error,
|
||||||
|
"details": {
|
||||||
|
"text": active_group.parameters.text,
|
||||||
|
"languages": active_group.parameters.languages or active_group.languages,
|
||||||
|
"group": {
|
||||||
|
"id": active_group.id,
|
||||||
|
"name": active_group.name,
|
||||||
|
"endpoints": active_group.endpoints,
|
||||||
|
"languages": active_group.languages
|
||||||
|
},
|
||||||
|
"start_time": active_group.parameters.start_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elif self.last_completed_group_id is not None:
|
||||||
|
# Return the last completed announcement
|
||||||
|
completed_group = self.get_endpoint_group(self.last_completed_group_id)
|
||||||
|
return {
|
||||||
|
"state": completed_group.progress.current_state,
|
||||||
|
"progress": completed_group.progress.progress,
|
||||||
|
"error": completed_group.progress.error,
|
||||||
|
"details": {
|
||||||
|
"text": completed_group.parameters.text,
|
||||||
|
"languages": completed_group.parameters.languages or completed_group.languages,
|
||||||
|
"group": {
|
||||||
|
"id": completed_group.id,
|
||||||
|
"name": completed_group.name,
|
||||||
|
"endpoints": completed_group.endpoints,
|
||||||
|
"languages": completed_group.languages
|
||||||
|
},
|
||||||
|
"start_time": completed_group.parameters.start_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
# No active or completed announcements
|
||||||
|
return {
|
||||||
|
"state": AnnouncementStates.IDLE.value,
|
||||||
|
"progress": 0.0,
|
||||||
|
"error": None,
|
||||||
|
"details": {
|
||||||
|
"text": "",
|
||||||
|
"languages": [],
|
||||||
|
"group": {
|
||||||
|
"id": 0,
|
||||||
|
"name": "",
|
||||||
|
"endpoints": [],
|
||||||
|
"languages": []
|
||||||
|
},
|
||||||
|
"start_time": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Singleton instance
|
# Singleton instance
|
||||||
announcement_system = AnnouncementSystem()
|
announcement_system = AnnouncementSystem()
|
||||||
|
|||||||
Reference in New Issue
Block a user