def __bootstrap_device_settings(device_widget: DeviceSettingsWidget, config: dict): mapping = { "frequency": "spinBoxFreq", "sample_rate": "spinBoxSampleRate", "bandwidth": "spinBoxBandwidth", "gain": "spinBoxGain", "if_gain": "spinBoxIFGain", "baseband_gain": "spinBoxBasebandGain", "freq_correction": "spinBoxFreqCorrection" } if "name" in config: device_widget.ui.cbDevice.setCurrentText(config["name"]) for key, value in config.items(): widget = mapping.get(key, None) if widget: getattr(device_widget.ui, widget).setValue(value) device_widget.emit_editing_finished_signals()
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if constants.SETTINGS.value('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True) def create_connects(self): if self.rx_needed: self.device_settings_rx_widget.selected_device_changed.connect(self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) self.ui.btnSaveRX.clicked.connect(self.on_btn_save_rx_clicked) self.ui.checkBoxCaptureFullRX.clicked.connect(self.on_checkbox_capture_full_rx_clicked) self.ui.btnTestSniffSettings.clicked.connect(self.on_btn_test_sniff_settings_clicked) self.ui.btnOpenInAnalysis.clicked.connect(self.on_btn_open_in_analysis_clicked) if self.tx_needed: self.device_settings_tx_widget.selected_device_changed.connect(self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect(self.tx_parameters_changed.emit) self.ui.radioButtonTranscriptBit.clicked.connect(self.on_radio_button_transcript_bit_clicked) self.ui.radioButtonTranscriptHex.clicked.connect(self.on_radio_button_transcript_hex_clicked) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_btn_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_btn_save_log_clicked) self.ui.btnSaveTranscript.clicked.connect(self.on_btn_save_transcript_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled(len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def __get_full_transcript(self) -> list: return self.simulator.transcript.get_for_all_participants(all_rounds=True, use_bit=self.ui.radioButtonTranscriptBit.isChecked()) def update_view(self): for device_message in filter(None, map(str.rstrip, self.simulator.device_messages())): self.ui.textEditDevices.append(device_message) for log_msg in filter(None, map(str.rstrip, self.simulator.read_log_messages())): self.ui.textEditSimulation.append(log_msg) transcript = self.__get_full_transcript() for line in transcript[self.current_transcript_index:]: self.ui.textEditTranscript.append(line) self.current_transcript_index = len(transcript) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index() if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if self.scene_manager is None or not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.textEditTranscript.clear() self.current_transcript_index = 0 self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_editing_finished_signals() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_editing_finished_signals() if self.sniff_settings_widget: self.sniff_settings_widget.emit_editing_finished_signals() def update_transcript_view(self): self.ui.textEditTranscript.setText("\n".join(self.__get_full_transcript())) def closeEvent(self, event: QCloseEvent): self.timer.stop() self.simulator.stop() time.sleep(0.1) self.simulator.cleanup() self.emit_editing_finished_signals() if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_device_parameters_changed() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_device_parameters_changed() if self.sniff_settings_widget: self.sniff_settings_widget.emit_sniff_parameters_changed() super().closeEvent(event) @pyqtSlot() def on_simulation_started(self): for i in range(3): self.ui.tabWidgetSimulatorSettings.setTabEnabled(i, False) self.ui.checkBoxCaptureFullRX.setDisabled(True) self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") if not self.rx_needed: return rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = rx_device.data.real else: self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = np.array([]) else: self.scene_manager.data_array = np.array([]) self.scene_manager.scene.addText("Could not generate RX preview.") @pyqtSlot() def on_simulation_stopped(self): self.ui.tabWidgetSimulatorSettings.setTabEnabled(0, True) self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, self.rx_needed) self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, self.tx_needed) self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") self.ui.checkBoxCaptureFullRX.setEnabled(True) @pyqtSlot() def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) @pyqtSlot() def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) @pyqtSlot() def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() @pyqtSlot() def on_btn_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) @pyqtSlot() def on_btn_save_transcript_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save transcript", "", "Text file (*.txt)") if file_path[0] == "": return transcript = self.ui.textEditTranscript.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(transcript) except Exception as e: QMessageBox.critical(self, "Error saving transcript", e.args[0]) @pyqtSlot() def on_btn_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: if self.rx_needed: self.device_settings_rx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.sniffer.rcv_device.current_index = 0 self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.tx_needed: self.device_settings_tx_widget.emit_editing_finished_signals() self.simulator.start() @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.generic_error("Error occurred", str(e)) @pyqtSlot() def on_btn_test_sniff_settings_clicked(self): def on_dialog_finished(): self.device_settings_rx_widget.bootstrap(self.project_manager.simulator_rx_conf) self.sniff_settings_widget.bootstrap(self.project_manager.device_conf) self.device_settings_rx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() psd = ProtocolSniffDialog(self.project_manager, signals=self.sniff_settings_widget.signals, parent=self) psd.device_settings_widget.bootstrap(self.project_manager.simulator_rx_conf) psd.device_settings_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) psd.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) psd.finished.connect(on_dialog_finished) psd.ui.btnAccept.hide() psd.show() @pyqtSlot() def on_radio_button_transcript_hex_clicked(self): self.update_transcript_view() @pyqtSlot() def on_radio_button_transcript_bit_clicked(self): self.update_transcript_view() @pyqtSlot() def on_checkbox_capture_full_rx_clicked(self): self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager = LiveSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) @pyqtSlot() def on_btn_save_rx_clicked(self): rx_device = self.simulator.sniffer.rcv_device if isinstance(rx_device.data, np.ndarray): filename = FileOperator.get_save_file_name("simulation_capture.complex") if filename: rx_device.data[:rx_device.current_index].tofile(filename) self.rx_file_saved.emit(filename) @pyqtSlot() def on_btn_open_in_analysis_clicked(self): text = self.ui.textEditTranscript.toPlainText() if len(text) > 0: self.open_in_analysis_requested.emit(text) self.close()
class RecvDialog(QWidget): device_parameters_changed = pyqtSignal(dict) change_tab = pyqtSignal() start_after_close = pyqtSignal() def __init__(self, project_manager: ProjectManager, is_tx: bool, continuous_send_mode=False, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 # This flag is needed. Will cause memory leak otherwise. # self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) self.setFixedSize(QtCore.QSize(1000, 300)) # self.setMaximumSize(QtCore.QSize(500, 500)) util.set_splitter_stylesheet(self.ui.splitter) self.graphics_view = None # type: QGraphicsView self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) # self.ui.btnSave.setEnabled(False) self.start = 0 self.hide_send_ui_items() self.device_settings_widget = DeviceSettingsWidget( project_manager, is_tx, backend_handler=self.backend_handler, continuous_send_mode=continuous_send_mode) self.device_settings_widget.setMaximumSize(500, 300) # self.ui.scrollAreaWidgetContents_2.layout().insertWidget(0, self.device_settings_widget) if testing_mode: self.device_settings_widget.ui.cbDevice.setCurrentText( NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) try: self.restoreGeometry( constants.SETTINGS.value("{}/geometry".format( self.__class__.__name__))) except TypeError: pass self.ui.splitter.setSizes([0.3 * self.width(), 0.7 * self.width()]) # self.ui.splitter.setFixedSize(0.3 * self.width(), 0.7 * self.width()) @property def is_rx(self) -> bool: return not self.is_tx @property def has_empty_device_list(self): return self.device_settings_widget.ui.cbDevice.count() == 0 @property def device(self) -> VirtualDevice: return self.device_settings_widget.device @device.setter def device(self, value): self.device_settings_widget.device = value @property def selected_device_name(self) -> str: return self.device_settings_widget.ui.cbDevice.currentText() def _eliminate_graphic_view(self): if self.graphics_view is not None: self.graphics_view.eliminate() self.graphics_view = None def hide_send_ui_items(self): for item in ("sliderYscale1", "sliderYscale2", "label_y_scale", "label_y_scale2", "btnMon", "btnNuke2", "btnNuke1", "lcdNumber", "btnRecordIQ", "btnConf", "btnSave", "lblCurrentRepeatValue", "progressBarMessage", "lblRepeatText", "lSamplesSentText", "progressBarSample", "labelCurrentMessage"): getattr(self.ui, item).hide() def hide_receive_ui_items(self): for item in ("lSamplesCaptured", "lSamplesCapturedText", "lSignalSize", "lSignalSizeText", "lTime", "lTimeText", "labelReceiveBufferFull", "lReceiveBufferFullText"): #btnSave getattr(self.ui, item).hide() def set_device_ui_items_enabled(self, enabled: bool): self.device_settings_widget.setEnabled(enabled) def create_connects(self): self.ui.btnStart.clicked.connect(self.on_start_clicked) self.ui.btnStop.clicked.connect(self.on_stop_clicked) self.ui.btnClear.clicked.connect(self.on_clear_clicked) self.timer.timeout.connect(self.update_view) self.ui.sliderYscale.valueChanged.connect( self.on_slider_y_scale_value_changed) self.device_settings_widget.selected_device_changed.connect( self.on_selected_device_changed) self.device_settings_widget.device_parameters_changed.connect( self.device_parameters_changed.emit) def _create_device_connects(self): self.device.stopped.connect(self.on_device_stopped) self.device.started.connect(self.on_device_started) self.device.sender_needs_restart.connect(self._restart_device_thread) def reset(self): self.device.current_index = 0 self.device.current_iteration = 0 self.ui.lSamplesCaptured.setText("0") self.ui.lSignalSize.setText("0") self.ui.lTime.setText("0") self.ui.lblCurrentRepeatValue.setText("-") self.ui.progressBarSample.setValue(0) self.ui.progressBarMessage.setValue(0) # self.ui.btnSave.setEnabled(False) # def init_device(self): # pass def save_before_close(self): return True def emit_editing_finished_signals(self): self.device_settings_widget.emit_editing_finished_signals() @pyqtSlot() def on_selected_device_changed(self): if hasattr(self.scene_manager, "plot_data"): self.scene_manager.plot_data = None self.init_device() self.graphics_view.scene_manager = self.scene_manager self.graphics_view.setScene(self.scene_manager.scene) @pyqtSlot() def on_start_clicked(self): self.emit_editing_finished_signals() @pyqtSlot() def on_stop_clicked(self): self.device.stop("Stopped receiving: Stop button clicked") @pyqtSlot() def on_device_stopped(self): if self.graphics_view is not None: self.graphics_view.capturing_data = False self.set_device_ui_items_enabled(True) self.ui.btnStart.setEnabled(True) self.ui.btnSetting.setEnabled(True) self.ui.btnStop.setEnabled(False) # self.ui.btnStop.setEnabled(False) # self.ui.btnSave.setEnabled(self.device.current_index > 0) self.device_settings_widget.ui.comboBoxDeviceIdentifier.setEnabled( True) self.device_settings_widget.ui.btnRefreshDeviceIdentifier.setEnabled( True) self.device_settings_widget.set_bandwidth_status() self.timer.stop() self.update_view() @pyqtSlot() def on_device_started(self): self.ui.txtEditErrors.clear() if self.graphics_view is not None: self.graphics_view.capturing_data = True #--------------------------------------- self.ui.btnSave.setEnabled(True) # --------------------------------------- self.ui.btnStart.setEnabled(False) self.ui.btnStop.setEnabled(True) # self.ui.btnSetting.setEnabled(True) self.device_settings_widget.ui.comboBoxDeviceIdentifier.setEnabled( False) self.device_settings_widget.ui.btnRefreshDeviceIdentifier.setEnabled( False) self.timer.start(self.update_interval) def __parse_error_messages(self, messages): messages = messages.lower() if "no devices found for" in messages: self.device.stop_on_error("Could not establish connection to USRP") Errors.usrp_found() self.on_clear_clicked() elif any(e in messages for e in ("hackrf_error_not_found", "hackrf_error_libusb")): self.device.stop_on_error( "Could not establish connection to HackRF") Errors.hackrf_not_found() self.on_clear_clicked() elif "no module named gnuradio" in messages: self.device.stop_on_error("Did not find gnuradio.") Errors.gnuradio_not_installed() self.on_clear_clicked() elif "rtlsdr-open: error code: -1" in messages: self.device.stop_on_error("Could not open a RTL-SDR device.") self.on_clear_clicked() elif "rtlsdr-open: error code: -12" in messages: self.device.stop_on_error("Could not open a RTL-SDR device") Errors.rtlsdr_sdr_driver() self.on_clear_clicked() elif "Address already in use" in messages: self._restart_device_thread() def update_view(self): try: self.ui.sliderYscale.setValue( int(self.graphics_view.transform().m22())) except AttributeError: return txt = self.ui.txtEditErrors.toPlainText() new_messages = self.device.read_messages() self.__parse_error_messages(new_messages) if len(new_messages) > 1: self.ui.txtEditErrors.setPlainText(txt + new_messages) self.ui.lSamplesCaptured.setText( Formatter.big_value_with_suffix(self.device.current_index, decimals=1)) self.ui.lSignalSize.setText( locale.format_string("%.2f Мб", (8 * self.device.current_index) / (1024**2))) self.ui.lTime.setText( locale.format_string( "%.2f с", self.device.current_index / self.device.sample_rate)) # if self.is_rx and self.device.data is not None and len(self.device.data) > 0: # self.ui.labelReceiveBufferFull.setText("{0}%".format(int(100 * self.device.current_index / # len(self.device.data)))) if self.device.current_index == 0: return False return True def _restart_device_thread(self): self.device.stop("Restarting with new port") if self.device.backend == Backends.grc: self.device.increase_gr_port() self.device.start() @pyqtSlot() def on_clear_clicked(self): pass def closeEvent(self, event: QCloseEvent): if self.device.backend is not Backends.none: self.emit_editing_finished_signals() self.timer.stop() self.device.stop("Dialog closed. Killing recording process.") logger.debug("Device stopped successfully.") if not self.testing_mode: if not self.save_before_close(): event.ignore() return time.sleep(0.1) if self.device.backend not in (Backends.none, Backends.network): # Backend none is selected, when no device is available logger.debug("Cleaning up device") self.device.cleanup() logger.debug("Successfully cleaned up device") self.device_settings_widget.emit_device_parameters_changed() constants.SETTINGS.setValue( "{}/geometry".format(self.__class__.__name__), self.saveGeometry()) if self.device is not None: self.device.free_data() self.scene_manager.eliminate() self._eliminate_graphic_view() self.on_stop_clicked() self.start_after_close.emit() super().closeEvent(event) @pyqtSlot(int) def on_slider_y_scale_value_changed(self, new_value: int): pass
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.simulator_config = simulator_config self.simulator_scene = SimulatorScene( mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() self.device_settings_rx_widget = DeviceSettingsWidget( project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget( self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, real_time=True, network_raw_mode=True) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget( 1, self.sniff_settings_widget) self.device_settings_tx_widget = DeviceSettingsWidget( project_manager, is_tx=True, backend_handler=self.backend_handler) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget( 1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=self.sniff_settings_widget.sniffer, sender=EndlessSender( self.backend_handler, send_device)) self.device_settings_tx_widget.device = self.simulator.sender.device self.scene_manager = SniffSceneManager(np.array([]), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) self.update_buttons() self.create_connects() self.__bootstrap_device_settings(self.device_settings_rx_widget, project_manager.simulator_rx_conf) self.__bootstrap_sniff_settings(self.sniff_settings_widget, project_manager.simulator_rx_conf) self.__bootstrap_device_settings(self.device_settings_tx_widget, project_manager.simulator_tx_conf) @staticmethod def __bootstrap_device_settings(device_widget: DeviceSettingsWidget, config: dict): mapping = { "frequency": "spinBoxFreq", "sample_rate": "spinBoxSampleRate", "bandwidth": "spinBoxBandwidth", "gain": "spinBoxGain", "if_gain": "spinBoxIFGain", "baseband_gain": "spinBoxBasebandGain", "freq_correction": "spinBoxFreqCorrection" } if "name" in config: device_widget.ui.cbDevice.setCurrentText(config["name"]) for key, value in config.items(): widget = mapping.get(key, None) if widget: getattr(device_widget.ui, widget).setValue(value) device_widget.emit_editing_finished_signals() @staticmethod def __bootstrap_sniff_settings(sniff_widget: SniffSettingsWidget, config: dict): for key, value in config.items(): if key == "bit_len": sniff_widget.ui.spinbox_sniff_BitLen.setValue(value) elif key == "center": sniff_widget.ui.spinbox_sniff_Center.setValue(value) elif key == "noise": sniff_widget.ui.spinbox_sniff_Noise.setValue(value) elif key == "tolerance": sniff_widget.ui.spinbox_sniff_ErrorTolerance.setValue(value) elif key == "modulation_index": sniff_widget.ui.combox_sniff_Modulation.setCurrentIndex( int(value)) elif key == "decoding_name": sniff_widget.ui.comboBox_sniff_encoding.setCurrentText(value) sniff_widget.emit_editing_finished_signals() def create_connects(self): self.device_settings_rx_widget.selected_device_changed.connect( self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect( self.rx_parameters_changed.emit) self.device_settings_tx_widget.selected_device_changed.connect( self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect( self.tx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect( self.sniff_parameters_changed.emit) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_save_log_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled( len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def update_view(self): txt = self.ui.textEditDevices.toPlainText() device_messages = self.simulator.device_messages() if len(device_messages) > 1: self.ui.textEditDevices.setPlainText(txt + device_messages) txt = self.ui.textEditSimulation.toPlainText() simulator_messages = self.simulator.read_messages() if len(simulator_messages) > 1: self.ui.textEditSimulation.setPlainText(txt + simulator_messages) self.ui.textEditSimulation.verticalScrollBar().setValue( self.ui.textEditSimulation.verticalScrollBar().maximum()) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index( ) if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def on_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) def on_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: self.device_settings_rx_widget.emit_editing_finished_signals() self.device_settings_tx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.start() def on_simulation_started(self): self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) self.scene_manager.data_array = np.array([]) self.scene_manager.scene.addText("Could not generate RX preview.") def on_simulation_stopped(self): self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): self.device_settings_rx_widget.emit_editing_finished_signals() self.device_settings_tx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() def closeEvent(self, event: QCloseEvent): self.emit_editing_finished_signals() self.device_settings_rx_widget.emit_device_parameters_changed() self.device_settings_tx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() self.timer.stop() self.simulator.stop() time.sleep(0.1) self.simulator.cleanup() super().closeEvent(event) @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.generic_error("Error occurred", str(e))
class SimulatorDialog(QDialog): rx_parameters_changed = pyqtSignal(dict) tx_parameters_changed = pyqtSignal(dict) sniff_parameters_changed = pyqtSignal(dict) open_in_analysis_requested = pyqtSignal(str) rx_file_saved = pyqtSignal(str) def __init__(self, simulator_config, modulators, expression_parser, project_manager: ProjectManager, signals: list = None, signal_tree_model=None, parent=None): super().__init__(parent) self.ui = Ui_DialogSimulator() self.ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.simulator_config = simulator_config # type: SimulatorConfiguration self.rx_needed = self.simulator_config.rx_needed self.tx_needed = self.simulator_config.tx_needed self.current_transcript_index = 0 self.simulator_scene = SimulatorScene(mode=1, simulator_config=self.simulator_config) self.ui.gvSimulator.setScene(self.simulator_scene) self.project_manager = project_manager self.update_interval = 25 self.timer = QTimer(self) self.backend_handler = BackendHandler() if self.rx_needed: self.device_settings_rx_widget = DeviceSettingsWidget(project_manager, is_tx=False, backend_handler=self.backend_handler) self.sniff_settings_widget = SniffSettingsWidget(self.device_settings_rx_widget.ui.cbDevice.currentText(), project_manager, signal=None, backend_handler=self.backend_handler, network_raw_mode=True, signals=signals) self.device_settings_rx_widget.device = self.sniff_settings_widget.sniffer.rcv_device self.sniff_settings_widget.ui.lineEdit_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_OutputFile.hide() self.sniff_settings_widget.ui.label_sniff_viewtype.hide() self.sniff_settings_widget.ui.checkBox_sniff_Timestamp.hide() self.sniff_settings_widget.ui.comboBox_sniff_viewtype.hide() self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(0, self.device_settings_rx_widget) self.ui.scrollAreaWidgetContentsRX.layout().insertWidget(1, self.sniff_settings_widget) sniffer = self.sniff_settings_widget.sniffer self.scene_manager = SniffSceneManager(np.array([], dtype=sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.device_settings_rx_widget = self.sniff_settings_widget = self.scene_manager = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, False) self.ui.graphicsViewPreview.hide() self.ui.btnSaveRX.hide() self.ui.checkBoxCaptureFullRX.hide() sniffer = None if self.tx_needed: self.device_settings_tx_widget = DeviceSettingsWidget(project_manager, is_tx=True, backend_handler=self.backend_handler, continuous_send_mode=True) self.device_settings_tx_widget.ui.spinBoxNRepeat.hide() self.device_settings_tx_widget.ui.labelNRepeat.hide() self.modulation_settings_widget = ModulationSettingsWidget(modulators, signal_tree_model=signal_tree_model, parent=None) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(0, self.device_settings_tx_widget) self.ui.scrollAreaWidgetContentsTX.layout().insertWidget(1, self.modulation_settings_widget) send_device = self.device_settings_tx_widget.ui.cbDevice.currentText() sender = EndlessSender(self.backend_handler, send_device) else: self.device_settings_tx_widget = self.modulation_settings_widget = None self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, False) sender = None self.simulator = Simulator(self.simulator_config, modulators, expression_parser, project_manager, sniffer=sniffer, sender=sender) if self.device_settings_tx_widget: self.device_settings_tx_widget.device = self.simulator.sender.device self.update_buttons() self.create_connects() if self.device_settings_rx_widget: self.device_settings_rx_widget.bootstrap(project_manager.simulator_rx_conf) if self.device_settings_tx_widget: self.device_settings_tx_widget.bootstrap(project_manager.simulator_tx_conf) self.ui.textEditTranscript.setFont(util.get_monospace_font()) if settings.read('default_view', 0, int) == 1: self.ui.radioButtonTranscriptHex.setChecked(True) def create_connects(self): if self.rx_needed: self.device_settings_rx_widget.selected_device_changed.connect(self.on_selected_rx_device_changed) self.device_settings_rx_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) self.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) self.ui.btnSaveRX.clicked.connect(self.on_btn_save_rx_clicked) self.ui.checkBoxCaptureFullRX.clicked.connect(self.on_checkbox_capture_full_rx_clicked) self.ui.btnTestSniffSettings.clicked.connect(self.on_btn_test_sniff_settings_clicked) self.ui.btnOpenInAnalysis.clicked.connect(self.on_btn_open_in_analysis_clicked) if self.tx_needed: self.device_settings_tx_widget.selected_device_changed.connect(self.on_selected_tx_device_changed) self.device_settings_tx_widget.device_parameters_changed.connect(self.tx_parameters_changed.emit) self.ui.radioButtonTranscriptBit.clicked.connect(self.on_radio_button_transcript_bit_clicked) self.ui.radioButtonTranscriptHex.clicked.connect(self.on_radio_button_transcript_hex_clicked) self.simulator_scene.selectionChanged.connect(self.update_buttons) self.simulator_config.items_updated.connect(self.update_buttons) self.ui.btnLogAll.clicked.connect(self.on_btn_log_all_clicked) self.ui.btnLogNone.clicked.connect(self.on_btn_log_none_clicked) self.ui.btnToggleLog.clicked.connect(self.on_btn_toggle_clicked) self.ui.btnStartStop.clicked.connect(self.on_btn_start_stop_clicked) self.ui.btnSaveLog.clicked.connect(self.on_btn_save_log_clicked) self.ui.btnSaveTranscript.clicked.connect(self.on_btn_save_transcript_clicked) self.timer.timeout.connect(self.on_timer_timeout) self.simulator.simulation_started.connect(self.on_simulation_started) self.simulator.simulation_stopped.connect(self.on_simulation_stopped) def update_buttons(self): selectable_items = self.simulator_scene.selectable_items() all_items_selected = all(item.model_item.logging_active for item in selectable_items) any_item_selected = any(item.model_item.logging_active for item in selectable_items) self.ui.btnToggleLog.setEnabled(len(self.simulator_scene.selectedItems())) self.ui.btnLogAll.setEnabled(not all_items_selected) self.ui.btnLogNone.setEnabled(any_item_selected) def __get_full_transcript(self) -> list: return self.simulator.transcript.get_for_all_participants(all_rounds=True, use_bit=self.ui.radioButtonTranscriptBit.isChecked()) def update_view(self): for device_message in filter(None, map(str.rstrip, self.simulator.device_messages())): self.ui.textEditDevices.append(device_message) for log_msg in filter(None, map(str.rstrip, self.simulator.read_log_messages())): self.ui.textEditSimulation.append(log_msg) transcript = self.__get_full_transcript() for line in transcript[self.current_transcript_index:]: self.ui.textEditTranscript.append(line) self.current_transcript_index = len(transcript) current_repeat = str(self.simulator.current_repeat + 1) if self.simulator.is_simulating else "-" self.ui.lblCurrentRepeatValue.setText(current_repeat) current_item = self.simulator.current_item.index() if self.simulator.is_simulating else "-" self.ui.lblCurrentItemValue.setText(current_item) def update_rx_graphics_view(self): if self.scene_manager is None or not self.ui.graphicsViewPreview.isEnabled(): return self.scene_manager.end = self.simulator.sniffer.rcv_device.current_index self.scene_manager.init_scene() self.scene_manager.show_full_scene() self.ui.graphicsViewPreview.update() def reset(self): self.ui.textEditDevices.clear() self.ui.textEditSimulation.clear() self.ui.textEditTranscript.clear() self.current_transcript_index = 0 self.ui.lblCurrentRepeatValue.setText("-") self.ui.lblCurrentItemValue.setText("-") def emit_editing_finished_signals(self): if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_editing_finished_signals() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_editing_finished_signals() if self.sniff_settings_widget: self.sniff_settings_widget.emit_editing_finished_signals() def update_transcript_view(self): self.ui.textEditTranscript.setText("\n".join(self.__get_full_transcript())) def closeEvent(self, event: QCloseEvent): self.timer.stop() self.simulator.stop() self.simulator.cleanup() self.emit_editing_finished_signals() if self.device_settings_rx_widget: self.device_settings_rx_widget.emit_device_parameters_changed() if self.device_settings_tx_widget: self.device_settings_tx_widget.emit_device_parameters_changed() if self.sniff_settings_widget: self.sniff_settings_widget.emit_sniff_parameters_changed() super().closeEvent(event) @pyqtSlot() def on_simulation_started(self): for i in range(3): self.ui.tabWidgetSimulatorSettings.setTabEnabled(i, False) self.ui.checkBoxCaptureFullRX.setDisabled(True) self.reset() self.timer.start(self.update_interval) self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-stop")) self.ui.btnStartStop.setText("Stop") if not self.rx_needed: return rx_device = self.simulator.sniffer.rcv_device for item in self.scene_manager.scene.items(): if isinstance(item, QGraphicsTextItem): self.scene_manager.scene.removeItem(item) if hasattr(rx_device.data, "real"): self.ui.graphicsViewPreview.setEnabled(True) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = rx_device.data.real else: self.scene_manager.data_array = rx_device.data.real else: self.ui.graphicsViewPreview.setEnabled(False) if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager.plot_data = np.array([], dtype=rx_device.data_type) else: self.scene_manager.data_array = np.array([], dtype=rx_device.data_type) self.scene_manager.scene.addText("Could not generate RX preview.") @pyqtSlot() def on_simulation_stopped(self): self.ui.tabWidgetSimulatorSettings.setTabEnabled(0, True) self.ui.tabWidgetSimulatorSettings.setTabEnabled(1, self.rx_needed) self.ui.tabWidgetSimulatorSettings.setTabEnabled(2, self.tx_needed) self.timer.stop() self.update_view() self.ui.btnStartStop.setIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStartStop.setText("Start") self.ui.checkBoxCaptureFullRX.setEnabled(True) @pyqtSlot() def on_btn_log_all_clicked(self): self.simulator_scene.log_all_items(True) @pyqtSlot() def on_btn_log_none_clicked(self): self.simulator_scene.log_all_items(False) @pyqtSlot() def on_btn_toggle_clicked(self): self.simulator_scene.log_toggle_selected_items() @pyqtSlot() def on_btn_save_log_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save log", "", "Log file (*.log)") if file_path[0] == "": return log_string = self.ui.textEditSimulation.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(log_string) except Exception as e: QMessageBox.critical(self, "Error saving log", e.args[0]) @pyqtSlot() def on_btn_save_transcript_clicked(self): file_path = QFileDialog.getSaveFileName(self, "Save transcript", "", "Text file (*.txt)") if file_path[0] == "": return transcript = self.ui.textEditTranscript.toPlainText() try: with open(str(file_path[0]), "w") as f: f.write(transcript) except Exception as e: QMessageBox.critical(self, "Error saving transcript", e.args[0]) @pyqtSlot() def on_btn_start_stop_clicked(self): if self.simulator.is_simulating: self.simulator.stop() else: if self.rx_needed: self.device_settings_rx_widget.emit_editing_finished_signals() self.sniff_settings_widget.emit_editing_finished_signals() self.simulator.sniffer.rcv_device.current_index = 0 self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() if self.tx_needed: self.device_settings_tx_widget.emit_editing_finished_signals() self.simulator.start() @pyqtSlot() def on_timer_timeout(self): self.update_view() self.update_rx_graphics_view() @pyqtSlot() def on_selected_rx_device_changed(self): dev_name = self.device_settings_rx_widget.ui.cbDevice.currentText() self.simulator.sniffer.device_name = dev_name self.device_settings_rx_widget.device = self.simulator.sniffer.rcv_device self.__set_rx_scene() @pyqtSlot() def on_selected_tx_device_changed(self): old_name = self.simulator.sender.device_name try: dev_name = self.device_settings_tx_widget.ui.cbDevice.currentText() self.simulator.sender.device_name = dev_name self.device_settings_tx_widget.device = self.simulator.sender.device except Exception as e: self.device_settings_tx_widget.ui.cbDevice.setCurrentText(old_name) Errors.exception(e) @pyqtSlot() def on_btn_test_sniff_settings_clicked(self): def on_dialog_finished(): self.device_settings_rx_widget.bootstrap(self.project_manager.simulator_rx_conf) self.sniff_settings_widget.bootstrap(self.project_manager.device_conf) self.device_settings_rx_widget.emit_device_parameters_changed() self.sniff_settings_widget.emit_sniff_parameters_changed() psd = ProtocolSniffDialog(self.project_manager, signals=self.sniff_settings_widget.signals, parent=self) psd.device_settings_widget.bootstrap(self.project_manager.simulator_rx_conf) psd.device_settings_widget.device_parameters_changed.connect(self.rx_parameters_changed.emit) psd.sniff_settings_widget.sniff_parameters_changed.connect(self.sniff_parameters_changed.emit) psd.finished.connect(on_dialog_finished) psd.ui.btnAccept.hide() psd.show() @pyqtSlot() def on_radio_button_transcript_hex_clicked(self): self.update_transcript_view() @pyqtSlot() def on_radio_button_transcript_bit_clicked(self): self.update_transcript_view() def __set_rx_scene(self): if not self.rx_needed: return if self.ui.checkBoxCaptureFullRX.isChecked(): self.scene_manager = LiveSceneManager(np.array([], dtype=self.simulator.sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) else: self.scene_manager = SniffSceneManager(np.array([], dtype=self.simulator.sniffer.rcv_device.data_type), parent=self) self.ui.graphicsViewPreview.setScene(self.scene_manager.scene) @pyqtSlot() def on_checkbox_capture_full_rx_clicked(self): self.simulator.sniffer.rcv_device.resume_on_full_receive_buffer = not self.ui.checkBoxCaptureFullRX.isChecked() self.__set_rx_scene() @pyqtSlot() def on_btn_save_rx_clicked(self): rx_device = self.simulator.sniffer.rcv_device if isinstance(rx_device.data, np.ndarray) or isinstance(rx_device.data, IQArray): data = IQArray(rx_device.data[:rx_device.current_index]) filename = FileOperator.ask_signal_file_name_and_save("simulation_capture", data, sample_rate=rx_device.sample_rate, parent=self) if filename: data.tofile(filename) self.rx_file_saved.emit(filename) @pyqtSlot() def on_btn_open_in_analysis_clicked(self): text = self.ui.textEditTranscript.toPlainText() if len(text) > 0: self.open_in_analysis_requested.emit(text) self.close()
class SendRecvDialog(QDialog): device_parameters_changed = pyqtSignal(dict) def __init__(self, project_manager: ProjectManager, is_tx: bool, continuous_send_mode=False, parent=None, testing_mode=False): super().__init__(parent) self.is_tx = is_tx self.update_interval = 25 # This flag is needed. Will cause memory leak otherwise. self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.Window) self.testing_mode = testing_mode self.ui = Ui_SendRecvDialog() self.ui.setupUi(self) util.set_splitter_stylesheet(self.ui.splitter) self.graphics_view = None # type: QGraphicsView self.backend_handler = BackendHandler() self.ui.btnStop.setEnabled(False) self.ui.btnSave.setEnabled(False) self.start = 0 self.device_settings_widget = DeviceSettingsWidget(project_manager, is_tx, backend_handler=self.backend_handler, continuous_send_mode=continuous_send_mode) self.ui.scrollAreaWidgetContents_2.layout().insertWidget(0, self.device_settings_widget) if testing_mode: self.device_settings_widget.ui.cbDevice.setCurrentText(NetworkSDRInterfacePlugin.NETWORK_SDR_NAME) self.timer = QTimer(self) try: self.restoreGeometry(constants.SETTINGS.value("{}/geometry".format(self.__class__.__name__))) except TypeError: pass self.ui.splitter.setSizes([0.4 * self.width(), 0.6 * self.width()]) @property def is_rx(self) -> bool: return not self.is_tx @property def has_empty_device_list(self): return self.device_settings_widget.ui.cbDevice.count() == 0 @property def device(self) -> VirtualDevice: return self.device_settings_widget.device @device.setter def device(self, value): self.device_settings_widget.device = value @property def selected_device_name(self) -> str: return self.device_settings_widget.ui.cbDevice.currentText() def _eliminate_graphic_view(self): if self.graphics_view is not None: self.graphics_view.eliminate() self.graphics_view = None def hide_send_ui_items(self): for item in ("lblCurrentRepeatValue", "progressBarMessage", "lblRepeatText", "lSamplesSentText", "progressBarSample", "labelCurrentMessage"): getattr(self.ui, item).hide() def hide_receive_ui_items(self): for item in ("lSamplesCaptured", "lSamplesCapturedText", "lSignalSize", "lSignalSizeText", "lTime", "lTimeText", "btnSave", "labelReceiveBufferFull", "lReceiveBufferFullText"): getattr(self.ui, item).hide() def set_device_ui_items_enabled(self, enabled: bool): self.device_settings_widget.setEnabled(enabled) def create_connects(self): self.ui.btnStart.clicked.connect(self.on_start_clicked) self.ui.btnStop.clicked.connect(self.on_stop_clicked) self.ui.btnClear.clicked.connect(self.on_clear_clicked) self.timer.timeout.connect(self.update_view) self.ui.sliderYscale.valueChanged.connect(self.on_slider_y_scale_value_changed) self.device_settings_widget.selected_device_changed.connect(self.on_selected_device_changed) self.device_settings_widget.device_parameters_changed.connect(self.device_parameters_changed.emit) def _create_device_connects(self): self.device.stopped.connect(self.on_device_stopped) self.device.started.connect(self.on_device_started) self.device.sender_needs_restart.connect(self._restart_device_thread) def reset(self): self.device.current_index = 0 self.device.current_iteration = 0 self.ui.lSamplesCaptured.setText("0") self.ui.lSignalSize.setText("0") self.ui.lTime.setText("0") self.ui.lblCurrentRepeatValue.setText("-") self.ui.progressBarSample.setValue(0) self.ui.progressBarMessage.setValue(0) self.ui.btnSave.setEnabled(False) def init_device(self): pass def save_before_close(self): return True def emit_editing_finished_signals(self): self.device_settings_widget.emit_editing_finished_signals() @pyqtSlot() def on_selected_device_changed(self): if hasattr(self.scene_manager, "plot_data"): self.scene_manager.plot_data = None self.init_device() self.graphics_view.scene_manager = self.scene_manager self.graphics_view.setScene(self.scene_manager.scene) @pyqtSlot() def on_start_clicked(self): self.emit_editing_finished_signals() @pyqtSlot() def on_stop_clicked(self): self.device.stop("Stopped receiving: Stop button clicked") @pyqtSlot() def on_device_stopped(self): if self.graphics_view is not None: self.graphics_view.capturing_data = False self.set_device_ui_items_enabled(True) self.ui.btnStart.setEnabled(True) self.ui.btnStop.setEnabled(False) self.ui.btnSave.setEnabled(self.device.current_index > 0) self.device_settings_widget.ui.comboBoxDeviceIdentifier.setEnabled(True) self.device_settings_widget.ui.btnRefreshDeviceIdentifier.setEnabled(True) self.device_settings_widget.set_bandwidth_status() self.timer.stop() self.update_view() @pyqtSlot() def on_device_started(self): self.ui.txtEditErrors.clear() if self.graphics_view is not None: self.graphics_view.capturing_data = True self.ui.btnSave.setEnabled(False) self.ui.btnStart.setEnabled(False) self.ui.btnStop.setEnabled(True) self.device_settings_widget.ui.comboBoxDeviceIdentifier.setEnabled(False) self.device_settings_widget.ui.btnRefreshDeviceIdentifier.setEnabled(False) self.timer.start(self.update_interval) def __parse_error_messages(self, messages): messages = messages.lower() if "no devices found for" in messages: self.device.stop_on_error("Could not establish connection to USRP") Errors.usrp_found() self.on_clear_clicked() elif any(e in messages for e in ("hackrf_error_not_found", "hackrf_error_libusb")): self.device.stop_on_error("Could not establish connection to HackRF") Errors.hackrf_not_found() self.on_clear_clicked() elif "no module named gnuradio" in messages: self.device.stop_on_error("Did not find gnuradio.") Errors.gnuradio_not_installed() self.on_clear_clicked() elif "rtlsdr-open: error code: -1" in messages: self.device.stop_on_error("Could not open a RTL-SDR device.") self.on_clear_clicked() elif "rtlsdr-open: error code: -12" in messages: self.device.stop_on_error("Could not open a RTL-SDR device") Errors.rtlsdr_sdr_driver() self.on_clear_clicked() elif "Address already in use" in messages: self._restart_device_thread() def update_view(self): try: self.ui.sliderYscale.setValue(int(self.graphics_view.transform().m22())) except AttributeError: return txt = self.ui.txtEditErrors.toPlainText() new_messages = self.device.read_messages() self.__parse_error_messages(new_messages) if len(new_messages) > 1: self.ui.txtEditErrors.setPlainText(txt + new_messages) self.ui.lSamplesCaptured.setText(Formatter.big_value_with_suffix(self.device.current_index, decimals=1)) self.ui.lSignalSize.setText(locale.format_string("%.2f", (8 * self.device.current_index) / (1024 ** 2))) self.ui.lTime.setText(locale.format_string("%.2f", self.device.current_index / self.device.sample_rate)) if self.is_rx and self.device.data is not None and len(self.device.data) > 0: self.ui.labelReceiveBufferFull.setText("{0}%".format(int(100 * self.device.current_index / len(self.device.data)))) if self.device.current_index == 0: return False return True def _restart_device_thread(self): self.device.stop("Restarting with new port") if self.device.backend == Backends.grc: self.device.increase_gr_port() self.device.start() @pyqtSlot() def on_clear_clicked(self): pass def closeEvent(self, event: QCloseEvent): if self.device.backend is not Backends.none: self.emit_editing_finished_signals() self.timer.stop() self.device.stop("Dialog closed. Killing recording process.") logger.debug("Device stopped successfully.") if not self.testing_mode: if not self.save_before_close(): event.ignore() return time.sleep(0.1) if self.device.backend not in (Backends.none, Backends.network): # Backend none is selected, when no device is available logger.debug("Cleaning up device") self.device.cleanup() logger.debug("Successfully cleaned up device") self.device_settings_widget.emit_device_parameters_changed() constants.SETTINGS.setValue("{}/geometry".format(self.__class__.__name__), self.saveGeometry()) if self.device is not None: self.device.free_data() self.scene_manager.eliminate() self._eliminate_graphic_view() super().closeEvent(event) @pyqtSlot(int) def on_slider_y_scale_value_changed(self, new_value: int): # Scale Up = Top Half, Scale Down = Lower Half transform = self.graphics_view.transform() self.graphics_view.setTransform(QTransform(transform.m11(), transform.m12(), transform.m13(), transform.m21(), new_value, transform.m23(), transform.m31(), transform.m32(), transform.m33()))