add of gsm settings
All checks were successful
/ mirror (push) Successful in 4s

This commit is contained in:
Bartosz 2025-07-07 21:53:01 +01:00
parent 1d5eae7d80
commit 4cc9e8b2d2
2 changed files with 620 additions and 41 deletions

View File

@ -0,0 +1,330 @@
from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QFrame,
QGridLayout, QProgressBar
)
from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QPalette, QColor, QPainter, QBrush, QLinearGradient
import math
class SignalStrengthWidget(QWidget):
"""Custom widget to display signal strength bars"""
def __init__(self, parent=None):
super().__init__(parent)
self.signal_strength = -70 # dBm
self.setMinimumSize(60, 40)
self.setMaximumSize(80, 50)
def set_signal_strength(self, dbm):
self.signal_strength = dbm
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# Calculate number of bars based on signal strength
# -50 dBm or better = 5 bars
# -60 dBm = 4 bars
# -70 dBm = 3 bars
# -80 dBm = 2 bars
# -90 dBm = 1 bar
# < -90 dBm = 0 bars
if self.signal_strength >= -50:
active_bars = 5
elif self.signal_strength >= -60:
active_bars = 4
elif self.signal_strength >= -70:
active_bars = 3
elif self.signal_strength >= -80:
active_bars = 2
elif self.signal_strength >= -90:
active_bars = 1
else:
active_bars = 0
bar_width = 10
bar_spacing = 3
max_height = 35
for i in range(5):
x = i * (bar_width + bar_spacing) + 5
bar_height = (i + 1) * 7
y = max_height - bar_height + 10
if i < active_bars:
# Active bar - gradient from green to yellow to red based on strength
if self.signal_strength >= -60:
color = QColor(76, 175, 80) # Green
elif self.signal_strength >= -75:
color = QColor(255, 193, 7) # Amber
else:
color = QColor(244, 67, 54) # Red
else:
# Inactive bar
color = QColor(60, 60, 60)
painter.fillRect(x, y, bar_width, bar_height, color)
class GSMStatusWidget(QFrame):
"""Widget to display GSM network status and parameters"""
def __init__(self, parent=None):
super().__init__(parent)
self.setObjectName("gsmStatusWidget")
self.setFrameStyle(QFrame.StyledPanel)
# Default settings
self.settings = {
'signal_strength': -70,
'signal_quality': 75,
'noise_level': 10,
'codec_mode': 'AMR-NB',
'bitrate': 12.2,
'packet_loss': 0,
'jitter': 20,
'latency': 100,
'fading_enabled': False,
'fading_speed': 'slow',
'interference_enabled': False,
'handover_enabled': False
}
self.init_ui()
self.update_display()
def init_ui(self):
"""Initialize the UI components"""
main_layout = QVBoxLayout()
main_layout.setSpacing(10)
main_layout.setContentsMargins(15, 15, 15, 15)
# Title
title_label = QLabel("📡 GSM Network Status")
title_label.setObjectName("gsmStatusTitle")
title_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(title_label)
# Main status grid
status_grid = QGridLayout()
status_grid.setSpacing(12)
# Row 0: Signal strength visualization
status_grid.addWidget(QLabel("Signal:"), 0, 0)
self.signal_widget = SignalStrengthWidget()
status_grid.addWidget(self.signal_widget, 0, 1)
self.signal_dbm_label = QLabel("-70 dBm")
self.signal_dbm_label.setObjectName("signalDbmLabel")
status_grid.addWidget(self.signal_dbm_label, 0, 2)
# Row 1: Signal quality bar
status_grid.addWidget(QLabel("Quality:"), 1, 0)
self.quality_bar = QProgressBar()
self.quality_bar.setTextVisible(True)
self.quality_bar.setRange(0, 100)
self.quality_bar.setObjectName("qualityBar")
status_grid.addWidget(self.quality_bar, 1, 1, 1, 2)
# Row 2: Noise level
status_grid.addWidget(QLabel("Noise:"), 2, 0)
self.noise_bar = QProgressBar()
self.noise_bar.setTextVisible(True)
self.noise_bar.setRange(0, 50)
self.noise_bar.setObjectName("noiseBar")
status_grid.addWidget(self.noise_bar, 2, 1, 1, 2)
main_layout.addLayout(status_grid)
# Separator
separator1 = QFrame()
separator1.setFrameShape(QFrame.HLine)
separator1.setObjectName("gsmSeparator")
main_layout.addWidget(separator1)
# Codec info section
codec_layout = QHBoxLayout()
codec_layout.setSpacing(15)
codec_icon = QLabel("🎤")
codec_layout.addWidget(codec_icon)
self.codec_label = QLabel("AMR-NB @ 12.2 kbps")
self.codec_label.setObjectName("codecLabel")
codec_layout.addWidget(self.codec_label)
codec_layout.addStretch()
main_layout.addLayout(codec_layout)
# Network conditions section
network_grid = QGridLayout()
network_grid.setSpacing(8)
# Packet loss indicator
network_grid.addWidget(QLabel("📉"), 0, 0)
self.packet_loss_label = QLabel("Loss: 0%")
self.packet_loss_label.setObjectName("networkParam")
network_grid.addWidget(self.packet_loss_label, 0, 1)
# Jitter indicator
network_grid.addWidget(QLabel("📊"), 0, 2)
self.jitter_label = QLabel("Jitter: 20ms")
self.jitter_label.setObjectName("networkParam")
network_grid.addWidget(self.jitter_label, 0, 3)
# Latency indicator
network_grid.addWidget(QLabel(""), 1, 0)
self.latency_label = QLabel("Latency: 100ms")
self.latency_label.setObjectName("networkParam")
network_grid.addWidget(self.latency_label, 1, 1)
# Features status
network_grid.addWidget(QLabel("🌊"), 1, 2)
self.features_label = QLabel("Standard")
self.features_label.setObjectName("networkParam")
network_grid.addWidget(self.features_label, 1, 3)
main_layout.addLayout(network_grid)
# Connection status
separator2 = QFrame()
separator2.setFrameShape(QFrame.HLine)
separator2.setObjectName("gsmSeparator")
main_layout.addWidget(separator2)
self.connection_status = QLabel("🟢 Connected to GSM Network")
self.connection_status.setObjectName("connectionStatus")
self.connection_status.setAlignment(Qt.AlignCenter)
main_layout.addWidget(self.connection_status)
main_layout.addStretch()
self.setLayout(main_layout)
# Apply styling
self.setStyleSheet("""
#gsmStatusWidget {
background-color: #2A2A2A;
border: 2px solid #0078D4;
border-radius: 10px;
}
#gsmStatusTitle {
font-size: 16px;
font-weight: bold;
color: #00A2E8;
padding: 5px;
}
#signalDbmLabel {
font-size: 14px;
font-weight: bold;
color: #4CAF50;
}
#qualityBar {
background-color: #1E1E1E;
border: 1px solid #444;
border-radius: 3px;
text-align: center;
color: white;
}
#qualityBar::chunk {
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #4CAF50, stop:0.5 #8BC34A, stop:1 #CDDC39);
border-radius: 3px;
}
#noiseBar {
background-color: #1E1E1E;
border: 1px solid #444;
border-radius: 3px;
text-align: center;
color: white;
}
#noiseBar::chunk {
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #FFC107, stop:0.5 #FF9800, stop:1 #FF5722);
border-radius: 3px;
}
#codecLabel {
font-size: 13px;
color: #E0E0E0;
font-weight: bold;
}
#networkParam {
font-size: 12px;
color: #B0B0B0;
}
#gsmSeparator {
background-color: #444;
max-height: 1px;
margin: 5px 0;
}
#connectionStatus {
font-size: 13px;
color: #4CAF50;
font-weight: bold;
padding: 5px;
}
QLabel {
color: #E0E0E0;
}
""")
def update_settings(self, settings):
"""Update the displayed settings"""
self.settings = settings
self.update_display()
def update_display(self):
"""Update all display elements based on current settings"""
# Update signal strength
self.signal_widget.set_signal_strength(self.settings['signal_strength'])
self.signal_dbm_label.setText(f"{self.settings['signal_strength']} dBm")
# Color code the dBm label
if self.settings['signal_strength'] >= -60:
self.signal_dbm_label.setStyleSheet("color: #4CAF50;") # Green
elif self.settings['signal_strength'] >= -75:
self.signal_dbm_label.setStyleSheet("color: #FFC107;") # Amber
else:
self.signal_dbm_label.setStyleSheet("color: #FF5722;") # Red
# Update quality bar
self.quality_bar.setValue(self.settings['signal_quality'])
self.quality_bar.setFormat(f"{self.settings['signal_quality']}%")
# Update noise bar
self.noise_bar.setValue(self.settings['noise_level'])
self.noise_bar.setFormat(f"{self.settings['noise_level']}%")
# Update codec info
self.codec_label.setText(f"{self.settings['codec_mode']} @ {self.settings['bitrate']} kbps")
# Update network parameters
self.packet_loss_label.setText(f"Loss: {self.settings['packet_loss']}%")
self.jitter_label.setText(f"Jitter: {self.settings['jitter']}ms")
self.latency_label.setText(f"Latency: {self.settings['latency']}ms")
# Update features
features = []
if self.settings['fading_enabled']:
features.append(f"Fading({self.settings['fading_speed']})")
if self.settings['interference_enabled']:
features.append("Interference")
if self.settings['handover_enabled']:
features.append("Handover")
if features:
self.features_label.setText(", ".join(features))
else:
self.features_label.setText("Standard")
# Update connection status based on signal quality
if self.settings['signal_quality'] >= 80:
self.connection_status.setText("🟢 Excellent Connection")
self.connection_status.setStyleSheet("color: #4CAF50;")
elif self.settings['signal_quality'] >= 60:
self.connection_status.setText("🟡 Good Connection")
self.connection_status.setStyleSheet("color: #FFC107;")
elif self.settings['signal_quality'] >= 40:
self.connection_status.setText("🟠 Fair Connection")
self.connection_status.setStyleSheet("color: #FF9800;")
else:
self.connection_status.setText("🔴 Poor Connection")
self.connection_status.setStyleSheet("color: #FF5722;")

View File

@ -11,6 +11,8 @@ import threading
from phone_manager import PhoneManager
from waveform_widget import WaveformWidget
from phone_state import PhoneState
from gsm_settings_dialog import GSMSettingsDialog
from gsm_status_widget import GSMStatusWidget
class PhoneUI(QMainWindow):
debug_signal = pyqtSignal(str)
@ -27,45 +29,106 @@ class PhoneUI(QMainWindow):
self.auto_test_running = False
self.auto_test_timer = None
self.test_step = 0
# GSM settings dialog (will be created on demand)
self.gsm_settings_dialog = None
self.gsm_settings = None
# GSM simulation timer
self.gsm_simulation_timer = None
self.setStyleSheet("""
QMainWindow { background-color: #333333; }
QLabel { color: #E0E0E0; font-size: 14px; }
QPushButton {
background-color: #0078D4; color: white; border: none;
padding: 10px 15px; border-radius: 5px; font-size: 14px;
min-height: 30px;
QMainWindow {
background-color: #1a1a1a;
}
QLabel {
color: #E0E0E0;
font-size: 14px;
}
QPushButton {
background-color: #0078D4;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
font-size: 14px;
min-height: 30px;
font-weight: bold;
}
QPushButton:hover {
background-color: #005A9E;
}
QPushButton:pressed {
background-color: #003C6B;
}
QPushButton#settingsButton {
background-color: #555555;
}
QPushButton#settingsButton:hover {
background-color: #777777;
}
QPushButton:hover { background-color: #005A9E; }
QPushButton:pressed { background-color: #003C6B; }
QPushButton#settingsButton { background-color: #555555; }
QPushButton#settingsButton:hover { background-color: #777777; }
QFrame#phoneDisplay {
background-color: #1E1E1E; border: 2px solid #0078D4;
border-radius: 10px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #2A2A2A, stop:1 #1E1E1E);
border: 2px solid #0078D4;
border-radius: 12px;
}
QLabel#phoneTitleLabel {
font-size: 18px; font-weight: bold; padding-bottom: 5px;
font-size: 20px;
font-weight: bold;
padding: 10px;
color: #FFFFFF;
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #0078D4, stop:0.5 #00A2E8, stop:1 #0078D4);
border-radius: 8px;
margin-bottom: 5px;
}
QLabel#mainTitleLabel {
font-size: 24px; font-weight: bold; color: #00A2E8;
padding: 15px;
font-size: 28px;
font-weight: bold;
color: #00A2E8;
padding: 20px;
text-align: center;
letter-spacing: 1px;
}
QWidget#phoneWidget {
border: 2px solid #4A4A4A; border-radius: 10px;
background-color: #3A3A3A;
border: 2px solid #0078D4;
border-radius: 15px;
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #3A3A3A, stop:0.5 #2F2F2F, stop:1 #252525);
min-width: 400px;
padding: 10px;
padding: 15px;
margin: 5px;
}
QWidget#phoneWidget:hover {
border: 2px solid #00A2E8;
}
QTextEdit#debugConsole {
background-color: #1E1E1E; color: #00FF00;
font-family: monospace; font-size: 12px;
border: 2px solid #0078D4; border-radius: 5px;
background-color: #0a0a0a;
color: #00FF00;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
border: 2px solid #0078D4;
border-radius: 8px;
padding: 10px;
}
QPushButton#autoTestButton {
background-color: #FF8C00; min-height: 35px;
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #FF8C00, stop:1 #FFA500);
min-height: 35px;
font-size: 15px;
}
QPushButton#autoTestButton:hover {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #FF7F00, stop:1 #FF9500);
}
QSplitter::handle {
background-color: #0078D4;
width: 3px;
height: 3px;
}
QSplitter::handle:hover {
background-color: #00A2E8;
}
QPushButton#autoTestButton:hover { background-color: #FF7F00; }
""")
# Setup debug signal early
@ -81,9 +144,19 @@ class PhoneUI(QMainWindow):
main_layout = QVBoxLayout()
main_widget.setLayout(main_layout)
# Create splitter for phones and debug console
# Create main horizontal splitter for GSM status and phones/debug
self.main_h_splitter = QSplitter(Qt.Horizontal)
main_layout.addWidget(self.main_h_splitter)
# GSM Status Panel (left side)
self.gsm_status_widget = GSMStatusWidget()
self.gsm_status_widget.setMinimumWidth(280)
self.gsm_status_widget.setMaximumWidth(350)
self.main_h_splitter.addWidget(self.gsm_status_widget)
# Create vertical splitter for phones and debug console (right side)
self.splitter = QSplitter(Qt.Vertical)
main_layout.addWidget(self.splitter)
self.main_h_splitter.addWidget(self.splitter)
# Top widget for phones
phones_widget = QWidget()
@ -188,8 +261,9 @@ class PhoneUI(QMainWindow):
self.debug_console.append(msg)
del self._debug_queue
# Set splitter sizes (70% phones, 30% debug)
self.splitter.setSizes([600, 300])
# Set splitter sizes
self.splitter.setSizes([600, 300]) # 70% phones, 30% debug
self.main_h_splitter.setSizes([300, 1100]) # GSM panel: 300px, rest: 1100px
# Initialize UI
for phone in self.manager.phones:
@ -343,25 +417,69 @@ class PhoneUI(QMainWindow):
status_label = phone['status_label']
if state == PhoneState.IDLE:
button.setText("Call")
button.setText("📞 Call")
button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
status_label.setText("Idle")
button.setStyleSheet("background-color: #0078D4;")
status_label.setText("📱 Idle")
status_label.setStyleSheet("font-size: 18px; color: #888888;")
button.setStyleSheet("""
QPushButton {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #0078D4, stop:1 #005A9E);
font-weight: bold;
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #00A2E8, stop:1 #0078D4);
}
""")
elif state == PhoneState.CALLING:
button.setText("Cancel")
button.setText("Cancel")
button.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
status_label.setText(f"Calling {phone_number}...")
button.setStyleSheet("background-color: #E81123;")
status_label.setText(f"📲 Calling {phone_number}...")
status_label.setStyleSheet("font-size: 18px; color: #FFC107;")
button.setStyleSheet("""
QPushButton {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #E81123, stop:1 #B20F1F);
font-weight: bold;
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #FF1133, stop:1 #E81123);
}
""")
elif state == PhoneState.IN_CALL:
button.setText("Hang Up")
button.setText("📵 Hang Up")
button.setIcon(self.style().standardIcon(QStyle.SP_DialogCancelButton))
status_label.setText(f"In Call with {phone_number}")
button.setStyleSheet("background-color: #E81123;")
status_label.setText(f"📞 In Call with {phone_number}")
status_label.setStyleSheet("font-size: 18px; color: #4CAF50;")
button.setStyleSheet("""
QPushButton {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #E81123, stop:1 #B20F1F);
font-weight: bold;
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #FF1133, stop:1 #E81123);
}
""")
elif state == PhoneState.RINGING:
button.setText("Answer")
button.setText("Answer")
button.setIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton))
status_label.setText(f"Incoming Call from {phone_number}")
button.setStyleSheet("background-color: #107C10;")
status_label.setText(f"📱 Incoming Call from {phone_number}")
status_label.setStyleSheet("font-size: 18px; color: #4CAF50; font-weight: bold;")
button.setStyleSheet("""
QPushButton {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #107C10, stop:1 #0B5C0B);
font-weight: bold;
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #20AC20, stop:1 #107C10);
}
""")
def set_phone_state(self, client_id, state_str, number):
self.debug(f"Phone {client_id + 1} state change: {state_str}")
@ -370,18 +488,26 @@ class PhoneUI(QMainWindow):
if state_str == "HANDSHAKE_COMPLETE":
phone = self.manager.phones[client_id]
phone['status_label'].setText("🔒 Secure Channel Established")
phone['status_label'].setStyleSheet("font-size: 16px; color: #00A2E8; font-weight: bold;")
self.debug(f"Phone {client_id + 1} secure channel established")
self.manager.start_audio(client_id, parent=self)
return
elif state_str == "VOICE_START":
phone = self.manager.phones[client_id]
phone['status_label'].setText("🎤 Voice Active (Encrypted)")
phone['status_label'].setStyleSheet("font-size: 16px; color: #4CAF50; font-weight: bold;")
self.debug(f"Phone {client_id + 1} voice session started")
# Start simulating real-time GSM parameter updates if we have settings
if hasattr(self, 'gsm_settings') and self.gsm_settings:
self.start_gsm_simulation()
return
elif state_str == "VOICE_END":
phone = self.manager.phones[client_id]
phone['status_label'].setText("🔒 Secure Channel")
phone['status_label'].setStyleSheet("font-size: 16px; color: #00A2E8;")
self.debug(f"Phone {client_id + 1} voice session ended")
# Stop GSM simulation
self.stop_gsm_simulation()
return
# Handle regular states
@ -409,8 +535,61 @@ class PhoneUI(QMainWindow):
self.update_phone_ui(client_id)
def settings_action(self):
print("Settings clicked")
self.debug("Settings clicked")
"""Show GSM settings dialog"""
self.debug("Opening GSM settings dialog")
# Create dialog if not exists (lazy initialization)
if self.gsm_settings_dialog is None:
self.gsm_settings_dialog = GSMSettingsDialog(self)
# Connect signal to handle settings changes
self.gsm_settings_dialog.settings_changed.connect(self.on_gsm_settings_changed)
# Show dialog
if self.gsm_settings_dialog.exec_():
# User clicked OK, get the settings
self.gsm_settings = self.gsm_settings_dialog.get_settings()
self.debug("GSM settings updated:")
self.debug(f" Signal strength: {self.gsm_settings['signal_strength']} dBm")
self.debug(f" Signal quality: {self.gsm_settings['signal_quality']}%")
self.debug(f" Noise level: {self.gsm_settings['noise_level']}%")
self.debug(f" Codec: {self.gsm_settings['codec_mode']} @ {self.gsm_settings['bitrate']} kbps")
self.debug(f" Network conditions - Packet loss: {self.gsm_settings['packet_loss']}%, Jitter: {self.gsm_settings['jitter']}ms, Latency: {self.gsm_settings['latency']}ms")
# Apply settings to phones if needed
self.apply_gsm_settings()
# Update GSM status widget
self.gsm_status_widget.update_settings(self.gsm_settings)
else:
self.debug("GSM settings dialog cancelled")
def on_gsm_settings_changed(self, settings):
"""Handle real-time settings changes if needed"""
self.gsm_settings = settings
self.debug("GSM settings changed (real-time update)")
# Update GSM status widget in real-time
self.gsm_status_widget.update_settings(settings)
def apply_gsm_settings(self):
"""Apply GSM settings to the phone simulation"""
if self.gsm_settings:
# Here you can apply the settings to your phone manager or simulation
# For example, update signal quality indicators, adjust codec parameters, etc.
self.debug("Applying GSM settings to simulation...")
# Update UI to reflect signal conditions
for phone_id, phone in enumerate(self.manager.phones):
signal_quality = self.gsm_settings['signal_quality']
if signal_quality >= 80:
signal_icon = "📶" # Full signal
elif signal_quality >= 60:
signal_icon = "📶" # Good signal
elif signal_quality >= 40:
signal_icon = "📵" # Fair signal
else:
signal_icon = "📵" # Poor signal
# You can update status labels or other UI elements here
self.debug(f"Phone {phone_id + 1} signal quality: {signal_quality}% {signal_icon}")
def debug(self, message):
"""Thread-safe debug logging to both console and UI"""
@ -714,6 +893,7 @@ class PhoneUI(QMainWindow):
QShortcut(QKeySequence("Space"), self, self.toggle_auto_test)
QShortcut(QKeySequence("Ctrl+L"), self, self.clear_debug)
QShortcut(QKeySequence("Ctrl+A"), self, self.show_audio_menu)
QShortcut(QKeySequence("Ctrl+G"), self, self.settings_action)
self.debug("Keyboard shortcuts enabled:")
self.debug(" 1/2: Phone action (call/answer/hangup)")
@ -722,15 +902,84 @@ class PhoneUI(QMainWindow):
self.debug(" Space: Toggle auto test")
self.debug(" Ctrl+L: Clear debug")
self.debug(" Ctrl+A: Audio options menu")
self.debug(" Ctrl+G: GSM settings")
def start_gsm_simulation(self):
"""Start simulating GSM parameter changes during call"""
if not self.gsm_simulation_timer:
self.gsm_simulation_timer = QTimer()
self.gsm_simulation_timer.timeout.connect(self.update_gsm_simulation)
self.gsm_simulation_timer.start(1000) # Update every second
self.debug("Started GSM parameter simulation")
def stop_gsm_simulation(self):
"""Stop GSM parameter simulation"""
if self.gsm_simulation_timer:
self.gsm_simulation_timer.stop()
self.gsm_simulation_timer = None
self.debug("Stopped GSM parameter simulation")
def update_gsm_simulation(self):
"""Simulate realistic GSM parameter variations during call"""
if not hasattr(self, 'gsm_settings') or not self.gsm_settings:
return
import random
# Simulate signal strength variation (±2 dBm)
current_strength = self.gsm_settings['signal_strength']
variation = random.uniform(-2, 2)
new_strength = max(-120, min(-40, current_strength + variation))
self.gsm_settings['signal_strength'] = int(new_strength)
# Simulate signal quality variation (±3%)
current_quality = self.gsm_settings['signal_quality']
quality_variation = random.uniform(-3, 3)
new_quality = max(0, min(100, current_quality + quality_variation))
self.gsm_settings['signal_quality'] = int(new_quality)
# Simulate noise level variation (±1%)
current_noise = self.gsm_settings['noise_level']
noise_variation = random.uniform(-1, 2)
new_noise = max(0, min(50, current_noise + noise_variation))
self.gsm_settings['noise_level'] = int(new_noise)
# Simulate packet loss variation (occasional spikes)
if random.random() < 0.1: # 10% chance of packet loss spike
self.gsm_settings['packet_loss'] = random.randint(1, 5)
else:
self.gsm_settings['packet_loss'] = 0
# Simulate jitter variation (±5ms)
current_jitter = self.gsm_settings['jitter']
jitter_variation = random.uniform(-5, 5)
new_jitter = max(0, min(200, current_jitter + jitter_variation))
self.gsm_settings['jitter'] = int(new_jitter)
# Update the GSM status widget
self.gsm_status_widget.update_settings(self.gsm_settings)
def closeEvent(self, event):
if self.auto_test_running:
self.stop_auto_test()
# Stop GSM simulation
self.stop_gsm_simulation()
# Clean up GSM settings dialog
if self.gsm_settings_dialog is not None:
self.gsm_settings_dialog.close()
self.gsm_settings_dialog.deleteLater()
self.gsm_settings_dialog = None
# Clean up audio player
if hasattr(self.manager, 'audio_player'):
self.manager.audio_player.cleanup()
# Stop all phone clients
for phone in self.manager.phones:
phone['client'].stop()
event.accept()
if __name__ == "__main__":