""" System Status Panel Displays the status of cameras, AI models, and hardware. Allows manual refresh of status information. """ from typing import Optional, Dict, Any, Callable from PyQt5.QtWidgets import QGroupBox, QVBoxLayout, QHBoxLayout, QLabel, QPushButton from PyQt5.QtGui import QFont from PyQt5.QtCore import Qt from ui.widgets.status_indicator import StatusIndicator from resources.styles import GROUP_BOX_STYLE, HEADER_LABEL_STYLE, INFO_LABEL_STYLE, STANDARD_BUTTON_STYLE from utils.config import MODEL_VERSIONS from utils.system_monitor import get_full_system_status class SystemStatusPanel(QGroupBox): """ Panel displaying real-time system status information. Shows: - Camera systems (RGB, Multispectral, Thermal, Audio) - AI models (Ripeness, Quality, Defect Detection, Maturity, Shape) - Hardware information (GPU, RAM) Includes manual refresh button to update all statuses on demand. """ def __init__(self): """Initialize the system status panel.""" super().__init__("System Status") self.setStyleSheet(GROUP_BOX_STYLE) # Store status update callback self.models = None # Store references to all status widgets for updates self.camera_status_indicators = {} self.camera_info_labels = {} self.model_status_indicators = {} self.model_info_labels = {} self.gpu_info_label = None self.ram_info_label = None self.init_ui() def init_ui(self): """Initialize the UI components.""" layout = QVBoxLayout() # Camera Systems Section self._add_camera_systems(layout) # AI Models Section self._add_ai_models(layout) # Hardware Section self._add_hardware_info(layout) # Refresh Button refresh_btn = QPushButton("šŸ”„ Refresh Status") refresh_btn.setStyleSheet(STANDARD_BUTTON_STYLE) refresh_btn.clicked.connect(self.refresh_status) layout.addWidget(refresh_btn) layout.addStretch() self.setLayout(layout) def _add_camera_systems(self, layout: QVBoxLayout): """Add camera systems section to layout.""" # Section header camera_label = QLabel("Camera Systems:") camera_label.setFont(QFont("Arial", 16, QFont.Bold)) camera_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 10px;") layout.addWidget(camera_label) camera_names = ["EOS Utility", "2nd Look", "AnalyzIR", "Audio System"] for camera_name in camera_names: camera_layout = QHBoxLayout() # Status indicator status_indicator = StatusIndicator("offline") camera_layout.addWidget(status_indicator) self.camera_status_indicators[camera_name] = status_indicator # Camera name name_label = QLabel(camera_name) name_label.setFont(QFont("Arial", 12)) camera_layout.addWidget(name_label) camera_layout.addStretch() # Info label (specs or DISCONNECTED) info_label = QLabel("Initializing...") info_label.setStyleSheet(INFO_LABEL_STYLE) camera_layout.addWidget(info_label) self.camera_info_labels[camera_name] = info_label layout.addLayout(camera_layout) def _add_ai_models(self, layout: QVBoxLayout): """Add AI models section to layout.""" # Section header ai_label = QLabel("AI Models:") ai_label.setFont(QFont("Arial", 16, QFont.Bold)) ai_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 15px;") layout.addWidget(ai_label) model_info = [ ('Ripeness', MODEL_VERSIONS.get('ripeness', '')), ('Quality', MODEL_VERSIONS.get('quality', '')), ('Defect', MODEL_VERSIONS.get('defect', '')), ('Maturity', MODEL_VERSIONS.get('maturity', '')), ('Shape', MODEL_VERSIONS.get('shape', '')), ] for model_display_name, version in model_info: model_layout = QHBoxLayout() # Status indicator status_indicator = StatusIndicator("offline") model_layout.addWidget(status_indicator) self.model_status_indicators[model_display_name] = status_indicator # Model name with version model_text = QLabel(f"{model_display_name} Model {version}") model_text.setFont(QFont("Arial", 12)) model_layout.addWidget(model_text) model_layout.addStretch() # Info label info_label = QLabel("Initializing...") info_label.setStyleSheet(INFO_LABEL_STYLE) model_layout.addWidget(info_label) self.model_info_labels[model_display_name] = info_label layout.addLayout(model_layout) def _add_hardware_info(self, layout: QVBoxLayout): """Add hardware information section to layout.""" # Section header hardware_label = QLabel("Hardware:") hardware_label.setFont(QFont("Arial", 16, QFont.Bold)) hardware_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 15px;") layout.addWidget(hardware_label) # GPU info self.gpu_info_label = QLabel("GPU: Initializing...") self.gpu_info_label.setStyleSheet("color: #2c3e50; font-size: 12px;") layout.addWidget(self.gpu_info_label) # RAM info self.ram_info_label = QLabel("RAM: Initializing...") self.ram_info_label.setStyleSheet("color: #2c3e50; font-size: 12px;") layout.addWidget(self.ram_info_label) def set_models_reference(self, models: Dict[str, Any]): """ Set reference to loaded models for status checking. Args: models: Dictionary of model instances from main_window """ self.models = models def refresh_status(self): """Refresh all system status information.""" try: print("\nšŸ”„ ============= REFRESH STATUS =============") print("šŸ”„ Refreshing system status...") print(f" Available camera_status_indicators: {list(self.camera_status_indicators.keys())}") print(f" Available model_status_indicators: {list(self.model_status_indicators.keys())}") # Get complete system status system_status = get_full_system_status(self.models) # Update camera status cameras_status = system_status['cameras'] print(f"\nšŸ“· Camera status returned: {cameras_status}") for camera_name, camera_info in cameras_status.items(): print(f" Processing camera: {camera_name}") if camera_name in self.camera_status_indicators: # Update indicator status = 'online' if camera_info['running'] else 'offline' self.camera_status_indicators[camera_name].set_status(status) print(f" āœ“ Updated status to: {status}") # Update info label info_text = camera_info['spec'] self.camera_info_labels[camera_name].setText(info_text) print(f" āœ“ Updated info to: {info_text}") # Update color for disconnected if not camera_info['running']: self.camera_info_labels[camera_name].setStyleSheet( "color: #e74c3c; font-size: 12px; font-weight: bold;" ) else: self.camera_info_labels[camera_name].setStyleSheet(INFO_LABEL_STYLE) else: print(f" āœ— WARNING: Not found in camera_status_indicators!") # Update model status models_status = system_status['models'] print(f"\nšŸ¤– Model status returned: {models_status}") for model_name, model_info in models_status.items(): print(f" Processing model: {model_name}") if model_name in self.model_status_indicators: # Update indicator self.model_status_indicators[model_name].set_status(model_info['status']) print(f" āœ“ Updated status to: {model_info['status']}") # Update info label self.model_info_labels[model_name].setText(model_info['info']) print(f" āœ“ Updated info to: {model_info['info']}") else: print(f" āœ— WARNING: Not found in model_status_indicators!") # Update GPU info gpu_info = system_status['gpu'] print(f"\nšŸ’¾ GPU info: {gpu_info['display']}") self.gpu_info_label.setText(gpu_info['display']) # Update RAM info ram_info = system_status['ram'] print(f"šŸ’¾ RAM info: {ram_info['display']}") self.ram_info_label.setText(ram_info['display']) print("āœ“ System status refresh complete\n") except Exception as e: print(f"āŒ Error refreshing system status: {e}") import traceback traceback.print_exc() def update_model_status(self, model_name: str, status: str, info_text: str = ""): """ Update the status of a specific model (for backward compatibility). Args: model_name: Name of the model ('ripeness', 'quality', or 'defect') status: Status ('online', 'offline', or 'updating') info_text: Optional info text to display """ # Map old model names to new display names model_map = { 'ripeness': 'Ripeness', 'quality': 'Quality', 'defect': 'Defect', 'maturity': 'Maturity', 'shape': 'Shape' } display_name = model_map.get(model_name, model_name) if display_name in self.model_status_indicators: self.model_status_indicators[display_name].set_status(status) if info_text: self.model_info_labels[display_name].setText(info_text)