system_status.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. """
  2. System Status Panel
  3. Displays the status of cameras, AI models, and hardware.
  4. Allows manual refresh of status information.
  5. """
  6. from typing import Optional, Dict, Any, Callable
  7. from PyQt5.QtWidgets import QGroupBox, QVBoxLayout, QHBoxLayout, QLabel, QPushButton
  8. from PyQt5.QtGui import QFont
  9. from PyQt5.QtCore import Qt
  10. from ui.widgets.status_indicator import StatusIndicator
  11. from resources.styles import GROUP_BOX_STYLE, HEADER_LABEL_STYLE, INFO_LABEL_STYLE, STANDARD_BUTTON_STYLE
  12. from utils.config import MODEL_VERSIONS
  13. from utils.system_monitor import get_full_system_status
  14. class SystemStatusPanel(QGroupBox):
  15. """
  16. Panel displaying real-time system status information.
  17. Shows:
  18. - Camera systems (RGB, Multispectral, Thermal, Audio)
  19. - AI models (Ripeness, Quality, Defect Detection, Maturity, Shape)
  20. - Hardware information (GPU, RAM)
  21. Includes manual refresh button to update all statuses on demand.
  22. """
  23. def __init__(self):
  24. """Initialize the system status panel."""
  25. super().__init__("System Status")
  26. self.setStyleSheet(GROUP_BOX_STYLE)
  27. # Store status update callback
  28. self.models = None
  29. # Store references to all status widgets for updates
  30. self.camera_status_indicators = {}
  31. self.camera_info_labels = {}
  32. self.model_status_indicators = {}
  33. self.model_info_labels = {}
  34. self.gpu_info_label = None
  35. self.ram_info_label = None
  36. self.init_ui()
  37. def init_ui(self):
  38. """Initialize the UI components."""
  39. layout = QVBoxLayout()
  40. # Camera Systems Section
  41. self._add_camera_systems(layout)
  42. # AI Models Section
  43. self._add_ai_models(layout)
  44. # Hardware Section
  45. self._add_hardware_info(layout)
  46. # Refresh Button
  47. refresh_btn = QPushButton("🔄 Refresh Status")
  48. refresh_btn.setStyleSheet(STANDARD_BUTTON_STYLE)
  49. refresh_btn.clicked.connect(self.refresh_status)
  50. layout.addWidget(refresh_btn)
  51. layout.addStretch()
  52. self.setLayout(layout)
  53. def _add_camera_systems(self, layout: QVBoxLayout):
  54. """Add camera systems section to layout."""
  55. # Section header
  56. camera_label = QLabel("Camera Systems:")
  57. camera_label.setFont(QFont("Arial", 16, QFont.Bold))
  58. camera_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 10px;")
  59. layout.addWidget(camera_label)
  60. camera_names = ["EOS Utility", "2nd Look", "AnalyzIR", "Audio System"]
  61. for camera_name in camera_names:
  62. camera_layout = QHBoxLayout()
  63. # Status indicator
  64. status_indicator = StatusIndicator("offline")
  65. camera_layout.addWidget(status_indicator)
  66. self.camera_status_indicators[camera_name] = status_indicator
  67. # Camera name
  68. name_label = QLabel(camera_name)
  69. name_label.setFont(QFont("Arial", 12))
  70. camera_layout.addWidget(name_label)
  71. camera_layout.addStretch()
  72. # Info label (specs or DISCONNECTED)
  73. info_label = QLabel("Initializing...")
  74. info_label.setStyleSheet(INFO_LABEL_STYLE)
  75. camera_layout.addWidget(info_label)
  76. self.camera_info_labels[camera_name] = info_label
  77. layout.addLayout(camera_layout)
  78. def _add_ai_models(self, layout: QVBoxLayout):
  79. """Add AI models section to layout."""
  80. # Section header
  81. ai_label = QLabel("AI Models:")
  82. ai_label.setFont(QFont("Arial", 16, QFont.Bold))
  83. ai_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 15px;")
  84. layout.addWidget(ai_label)
  85. model_info = [
  86. ('Ripeness', MODEL_VERSIONS.get('ripeness', '')),
  87. ('Quality', MODEL_VERSIONS.get('quality', '')),
  88. ('Defect', MODEL_VERSIONS.get('defect', '')),
  89. ('Maturity', MODEL_VERSIONS.get('maturity', '')),
  90. ('Shape', MODEL_VERSIONS.get('shape', '')),
  91. ]
  92. for model_display_name, version in model_info:
  93. model_layout = QHBoxLayout()
  94. # Status indicator
  95. status_indicator = StatusIndicator("offline")
  96. model_layout.addWidget(status_indicator)
  97. self.model_status_indicators[model_display_name] = status_indicator
  98. # Model name with version
  99. model_text = QLabel(f"{model_display_name} Model {version}")
  100. model_text.setFont(QFont("Arial", 12))
  101. model_layout.addWidget(model_text)
  102. model_layout.addStretch()
  103. # Info label
  104. info_label = QLabel("Initializing...")
  105. info_label.setStyleSheet(INFO_LABEL_STYLE)
  106. model_layout.addWidget(info_label)
  107. self.model_info_labels[model_display_name] = info_label
  108. layout.addLayout(model_layout)
  109. def _add_hardware_info(self, layout: QVBoxLayout):
  110. """Add hardware information section to layout."""
  111. # Section header
  112. hardware_label = QLabel("Hardware:")
  113. hardware_label.setFont(QFont("Arial", 16, QFont.Bold))
  114. hardware_label.setStyleSheet(HEADER_LABEL_STYLE + " margin-top: 15px;")
  115. layout.addWidget(hardware_label)
  116. # GPU info
  117. self.gpu_info_label = QLabel("GPU: Initializing...")
  118. self.gpu_info_label.setStyleSheet("color: #2c3e50; font-size: 12px;")
  119. layout.addWidget(self.gpu_info_label)
  120. # RAM info
  121. self.ram_info_label = QLabel("RAM: Initializing...")
  122. self.ram_info_label.setStyleSheet("color: #2c3e50; font-size: 12px;")
  123. layout.addWidget(self.ram_info_label)
  124. def set_models_reference(self, models: Dict[str, Any]):
  125. """
  126. Set reference to loaded models for status checking.
  127. Args:
  128. models: Dictionary of model instances from main_window
  129. """
  130. self.models = models
  131. def refresh_status(self):
  132. """Refresh all system status information."""
  133. try:
  134. print("\n🔄 ============= REFRESH STATUS =============")
  135. print("🔄 Refreshing system status...")
  136. print(f" Available camera_status_indicators: {list(self.camera_status_indicators.keys())}")
  137. print(f" Available model_status_indicators: {list(self.model_status_indicators.keys())}")
  138. # Get complete system status
  139. system_status = get_full_system_status(self.models)
  140. # Update camera status
  141. cameras_status = system_status['cameras']
  142. print(f"\n📷 Camera status returned: {cameras_status}")
  143. for camera_name, camera_info in cameras_status.items():
  144. print(f" Processing camera: {camera_name}")
  145. if camera_name in self.camera_status_indicators:
  146. # Update indicator
  147. status = 'online' if camera_info['running'] else 'offline'
  148. self.camera_status_indicators[camera_name].set_status(status)
  149. print(f" ✓ Updated status to: {status}")
  150. # Update info label
  151. info_text = camera_info['spec']
  152. self.camera_info_labels[camera_name].setText(info_text)
  153. print(f" ✓ Updated info to: {info_text}")
  154. # Update color for disconnected
  155. if not camera_info['running']:
  156. self.camera_info_labels[camera_name].setStyleSheet(
  157. "color: #e74c3c; font-size: 12px; font-weight: bold;"
  158. )
  159. else:
  160. self.camera_info_labels[camera_name].setStyleSheet(INFO_LABEL_STYLE)
  161. else:
  162. print(f" ✗ WARNING: Not found in camera_status_indicators!")
  163. # Update model status
  164. models_status = system_status['models']
  165. print(f"\n🤖 Model status returned: {models_status}")
  166. for model_name, model_info in models_status.items():
  167. print(f" Processing model: {model_name}")
  168. if model_name in self.model_status_indicators:
  169. # Update indicator
  170. self.model_status_indicators[model_name].set_status(model_info['status'])
  171. print(f" ✓ Updated status to: {model_info['status']}")
  172. # Update info label
  173. self.model_info_labels[model_name].setText(model_info['info'])
  174. print(f" ✓ Updated info to: {model_info['info']}")
  175. else:
  176. print(f" ✗ WARNING: Not found in model_status_indicators!")
  177. # Update GPU info
  178. gpu_info = system_status['gpu']
  179. print(f"\n💾 GPU info: {gpu_info['display']}")
  180. self.gpu_info_label.setText(gpu_info['display'])
  181. # Update RAM info
  182. ram_info = system_status['ram']
  183. print(f"💾 RAM info: {ram_info['display']}")
  184. self.ram_info_label.setText(ram_info['display'])
  185. print("✓ System status refresh complete\n")
  186. except Exception as e:
  187. print(f"❌ Error refreshing system status: {e}")
  188. import traceback
  189. traceback.print_exc()
  190. def update_model_status(self, model_name: str, status: str, info_text: str = ""):
  191. """
  192. Update the status of a specific model (for backward compatibility).
  193. Args:
  194. model_name: Name of the model ('ripeness', 'quality', or 'defect')
  195. status: Status ('online', 'offline', or 'updating')
  196. info_text: Optional info text to display
  197. """
  198. # Map old model names to new display names
  199. model_map = {
  200. 'ripeness': 'Ripeness',
  201. 'quality': 'Quality',
  202. 'defect': 'Defect',
  203. 'maturity': 'Maturity',
  204. 'shape': 'Shape'
  205. }
  206. display_name = model_map.get(model_name, model_name)
  207. if display_name in self.model_status_indicators:
  208. self.model_status_indicators[display_name].set_status(status)
  209. if info_text:
  210. self.model_info_labels[display_name].setText(info_text)