示例#1
0
    def __init__(self, compare_frame_controller: CompareFrameController, project_manager: ProjectManager, parent=None):
        super().__init__(parent)
        self.ui = Ui_GeneratorTab()
        self.ui.setupUi(self)

        self.project_manager = project_manager

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = GeneratorTreeModel(compare_frame_controller)
        self.tree_model.set_root_item(compare_frame_controller.proto_tree_model.rootItem)
        self.tree_model.controller = self
        self.ui.treeProtocols.setModel(self.tree_model)

        self.table_model = GeneratorTableModel(compare_frame_controller.proto_tree_model.rootItem,
                                               [Modulator("Modulation")], compare_frame_controller.decodings)
        self.table_model.controller = self
        self.ui.tableMessages.setModel(self.table_model)

        self.label_list_model = GeneratorListModel(None)
        self.ui.listViewProtoLabels.setModel(self.label_list_model)

        self.network_sdr_button_orig_tooltip = self.ui.btnNetworkSDRSend.toolTip()
        self.set_network_sdr_send_button_visibility()
        self.set_rfcat_button_visibility()
        self.network_sdr_plugin = NetworkSDRInterfacePlugin()
        self.rfcat_plugin = RfCatPlugin()
        self.init_rfcat_plugin()

        self.refresh_modulators()
        self.on_selected_modulation_changed()
        self.set_fuzzing_ui_status()
        self.ui.prBarGeneration.hide()
        self.create_connects(compare_frame_controller)
示例#2
0
    def test_protocol_sniffer(self):
        samples_per_symbol = 100
        center = 0.0942
        noise = 0.1
        tolerance = 2
        modulation_type = "FSK"
        sample_rate = 1e6
        device_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        sniffer = ProtocolSniffer(samples_per_symbol=samples_per_symbol, center=center, center_spacing=0.1,
                                  noise=noise, tolerance=tolerance,
                                  modulation_type=modulation_type, bits_per_symbol=1,
                                  device=device_name, backend_handler=BackendHandler(),
                                  network_raw_mode=True)

        port = self.get_free_port()
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True)
        self.network_sdr_plugin_sender.client_port = port

        sniffer.sniff()
        QTest.qWait(10)

        data = ["101010", "000111", "1111000"]
        pause = 10 * samples_per_symbol
        modulator = Modulator("test")
        modulator.samples_per_symbol = samples_per_symbol
        modulator.sample_rate = sample_rate
        modulator.modulation_type = modulation_type
        modulator.parameters[1] = 20e3
        modulator.parameters[0] = 10e3

        packages = []
        for d in data:
            packages.append(modulator.modulate(list(map(int, d)), pause))

        # verify modulation was correct
        pa = ProtocolAnalyzer(None)
        signal = Signal("", "", sample_rate=sample_rate)
        signal.iq_array = IQArray.concatenate(packages)
        signal.modulation_type = modulation_type
        signal.samples_per_symbol = samples_per_symbol
        signal.tolerance = tolerance
        signal.noise_threshold = noise
        signal.center = center
        pa.signal = signal
        pa.get_protocol_from_signal()
        self.assertEqual(pa.plain_bits_str, data)

        # send data
        send_data = IQArray.concatenate(packages)
        self.network_sdr_plugin_sender.send_raw_data(send_data, 1)
        time.sleep(1)

        # Send enough pauses to end sniffing
        self.network_sdr_plugin_sender.send_raw_data(IQArray(None, np.float32, 10 * 2 * samples_per_symbol), 1)
        time.sleep(1)

        sniffer.stop()
        self.assertEqual(sniffer.plain_bits_str, data)
示例#3
0
    def test_protocol_sniffer(self):
        bit_len = 100
        center = 0.0942
        noise = 0.1
        tolerance = 2
        modulation_type = 1
        sample_rate = 1e6
        device_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        sniffer = ProtocolSniffer(bit_len=bit_len, center=center, noise=noise, tolerance=tolerance,
                                  modulation_type=modulation_type, device=device_name, backend_handler=BackendHandler(),
                                  network_raw_mode=True)

        port = self.get_free_port()
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True)
        self.network_sdr_plugin_sender.client_port = port

        sniffer.sniff()
        QTest.qWait(10)

        data = ["101010", "000111", "1111000"]
        pause = 10 * bit_len
        modulator = Modulator("test")
        modulator.samples_per_bit = bit_len
        modulator.sample_rate = sample_rate
        modulator.modulation_type = modulation_type
        modulator.param_for_one = 20e3
        modulator.param_for_zero = 10e3

        packages = []
        for d in data:
            packages.append(modulator.modulate(list(map(int, d)), pause))

        # verify modulation was correct
        pa = ProtocolAnalyzer(None)
        signal = Signal("", "", sample_rate=sample_rate)
        signal._fulldata = np.concatenate(packages)
        signal.modulation_type = modulation_type
        signal.bit_len = bit_len
        signal.tolerance = tolerance
        signal.noise_threshold = noise
        signal.qad_center = center
        pa.signal = signal
        pa.get_protocol_from_signal()
        self.assertEqual(pa.plain_bits_str, data)

        # send data
        send_data = np.concatenate(packages)
        self.network_sdr_plugin_sender.send_raw_data(send_data, 1)
        time.sleep(1)

        # Send enough pauses to end sniffing
        self.network_sdr_plugin_sender.send_raw_data(np.zeros(10 * bit_len, dtype=np.complex64), 1)
        time.sleep(1)

        sniffer.stop()
        self.assertEqual(sniffer.plain_bits_str, data)
示例#4
0
    def setUp(self):
        self.form = MainController()
        self.cfc = self.form.compare_frame_controller
        self.stc = self.form.simulator_tab_controller
        self.gtc = self.form.generator_tab_controller

        self.form.add_signalfile(get_path_for_data_file("esaver.complex"))
        self.sframe = self.form.signal_tab_controller.signal_frames[0]
        self.sim_frame = self.form.simulator_tab_controller
        self.form.ui.tabWidget.setCurrentIndex(3)
        self.cfc.proto_analyzer.auto_assign_labels()

        SettingsProxy.OVERWRITE_RECEIVE_BUFFER_SIZE = 100 * 10**6

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(
            raw_mode=True)
    def __init__(self, compare_frame_controller: CompareFrameController, project_manager: ProjectManager, parent=None):
        super().__init__(parent)
        self.ui = Ui_GeneratorTab()
        self.ui.setupUi(self)

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = GeneratorTreeModel(compare_frame_controller)
        self.tree_model.set_root_item(compare_frame_controller.proto_tree_model.rootItem)
        self.tree_model.controller = self
        self.ui.treeProtocols.setModel(self.tree_model)

        self.has_default_modulation = True

        self.table_model = GeneratorTableModel(compare_frame_controller.proto_tree_model.rootItem,
                                               [Modulator("Modulation")], compare_frame_controller.decodings)
        self.table_model.controller = self
        self.ui.tableMessages.setModel(self.table_model)

        self.label_list_model = GeneratorListModel(None)
        self.ui.listViewProtoLabels.setModel(self.label_list_model)

        self.network_sdr_button_orig_tooltip = self.ui.btnNetworkSDRSend.toolTip()
        self.set_network_sdr_send_button_visibility()
        self.set_rfcat_button_visibility()
        self.network_sdr_plugin = NetworkSDRInterfacePlugin()
        self.rfcat_plugin = RfCatPlugin()
        self.init_rfcat_plugin()

        self.refresh_modulators()
        self.on_selected_modulation_changed()
        self.set_fuzzing_ui_status()
        self.project_manager = project_manager
        self.ui.prBarGeneration.hide()
        self.create_connects(compare_frame_controller)
示例#6
0
    def test_sdr_interface_plugin(self):
        si = NetworkSDRInterfacePlugin()
        test_bits = [
            "10101011111", "1010100011000111110001011001010101010101",
            "1010100011000111110001011001010100100", "1101010101011000011",
            "11010101010110000110", "11100010101001110000",
            "111100000011011101010101010000101010101010100001010011010101010011"
        ]

        for bits in test_bits:
            byte_vals = si.bit_str_to_bytearray(bits)
            self.assertEqual(len(byte_vals),
                             int(math.ceil(len(bits) / 8)),
                             msg=bits)

            recalculated = si.bytearray_to_bit_str(byte_vals)

            if len(bits) % 8 == 0:
                self.assertEqual(bits, recalculated)
            elif bits.endswith("1"):
                self.assertEqual(bits, recalculated.rstrip("0"))
            else:
                self.assertTrue(recalculated.startswith(bits))
示例#7
0
    def test_sdr_interface_plugin(self):
        si = NetworkSDRInterfacePlugin(resume_on_full_receive_buffer=True)
        test_bits = [
            "10101011111",
            "1010100011000111110001011001010101010101",
            "1010100011000111110001011001010100100",
            "1101010101011000011",
            "11010101010110000110",
            "11100010101001110000",
            "111100000011011101010101010000101010101010100001010011010101010011"
        ]

        for bits in test_bits:
            byte_vals = si.bit_str_to_bytearray(bits)
            self.assertEqual(len(byte_vals), int(math.ceil(len(bits) / 8)), msg=bits)

            recalculated = si.bytearray_to_bit_str(byte_vals)

            if len(bits) % 8 == 0:
                self.assertEqual(bits, recalculated)
            elif bits.endswith("1"):
                self.assertEqual(bits, recalculated.rstrip("0"))
            else:
                self.assertTrue(recalculated.startswith(bits))
示例#8
0
    def test_open_simulator_dialog_and_send_mismatching_message(self):
        stc = self.form.simulator_tab_controller
        assert isinstance(stc, SimulatorTabController)

        self.__setup_project()
        self.add_all_signals_to_simulator()

        stc.simulator_scene.select_all_items()

        for msg in stc.simulator_scene.get_selected_messages():
            msg.destination = self.dennis
            stc.ui.gvSimulator.message_updated.emit(msg)

        list_model = stc.ui.listViewSimulate.model()
        self.assertEqual(list_model.rowCount(), 2)
        list_model.setData(list_model.createIndex(1, 0),
                           Qt.Checked,
                           role=Qt.CheckStateRole)

        dialog = stc.get_simulator_dialog()

        network_sdr_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(
            network_sdr_name)
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(
            network_sdr_name)

        send_port = self.get_free_port()
        dialog.simulator.sender.device.set_client_port(send_port)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", send_port))
        s.listen(1)

        rcv_port = self.get_free_port()
        dialog.simulator.sniffer.rcv_device.set_server_port(rcv_port)

        dialog.ui.btnStartStop.click()
        QTest.qWait(100)

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        sender = NetworkSDRInterfacePlugin(raw_mode=True, sending=True)
        sender.client_port = rcv_port
        sender.send_raw_data(modulator.modulate("1" * 352), 1)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)
        sender.send_raw_data(modulator.modulate("10" * 176), 1)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)
        QTest.qWait(1000)

        simulator_log = dialog.ui.textEditSimulation.toPlainText()
        self.assertIn("Received message 1", simulator_log)
        self.assertIn("preamble: 11111111", simulator_log)

        self.assertIn("Mismatch for label: preamble", simulator_log)

        dialog.close()
        s.close()
示例#9
0
class TestSimulator(QtTestCase):
    def setUp(self):
        super().setUp()
        SettingsProxy.OVERWRITE_RECEIVE_BUFFER_SIZE = 10 * 10**6

        self.num_zeros_for_pause = 1000

    def test_performance(self):
        self.form = MainController()
        self.cfc = self.form.compare_frame_controller
        self.stc = self.form.simulator_tab_controller
        self.gtc = self.form.generator_tab_controller

        self.form.add_signalfile(get_path_for_data_file("esaver.complex"))
        self.sframe = self.form.signal_tab_controller.signal_frames[0]
        self.sim_frame = self.form.simulator_tab_controller
        self.form.ui.tabWidget.setCurrentIndex(3)
        self.cfc.proto_analyzer.auto_assign_labels()

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(
            raw_mode=True)

        part_a = Participant("Device A", shortname="A", color_index=0)
        part_b = Participant("Device B", shortname="B", color_index=1)
        part_b.simulate = True

        self.form.project_manager.participants.append(part_a)
        self.form.project_manager.participants.append(part_b)
        self.form.project_manager.project_updated.emit()

        sniffer = ProtocolSniffer(100,
                                  0.01,
                                  0.1,
                                  5,
                                  1,
                                  NetworkSDRInterfacePlugin.NETWORK_SDR_NAME,
                                  BackendHandler(),
                                  network_raw_mode=True)
        sender = EndlessSender(BackendHandler(),
                               NetworkSDRInterfacePlugin.NETWORK_SDR_NAME)

        simulator = Simulator(self.stc.simulator_config,
                              self.gtc.modulators,
                              self.stc.sim_expression_parser,
                              self.form.project_manager,
                              sniffer=sniffer,
                              sender=sender)

        pause = 100000
        msg_a = SimulatorMessage(
            part_b, [1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 +
            [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
            pause=pause,
            message_type=MessageType("empty_message_type"),
            source=part_a)

        msg_b = SimulatorMessage(
            part_a, [1, 0] * 16 + [1, 1, 0, 0] * 8 + [1, 1, 0, 0] * 8 +
            [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
            pause=pause,
            message_type=MessageType("empty_message_type"),
            source=part_b)

        self.stc.simulator_config.add_items([msg_a, msg_b], 0, None)
        self.stc.simulator_config.update_active_participants()

        port = self.get_free_port()
        sniffer = simulator.sniffer
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender.client_port = port

        sender = simulator.sender
        port = self.get_free_port()
        sender.device.set_client_port(port)
        sender.device._VirtualDevice__dev.name = "simulator_sender"

        current_index = Value("L")
        elapsed = Value("f")
        target_num_samples = 113600 - pause
        receive_process = Process(target=receive,
                                  args=(port, current_index,
                                        target_num_samples, elapsed))
        receive_process.daemon = True
        receive_process.start()

        # Ensure receiver is running
        time.sleep(2)

        # spy = QSignalSpy(self.network_sdr_plugin_receiver.rcv_index_changed)
        simulator.start()

        modulator = Modulator("test_modulator")
        modulator.samples_per_bit = 100
        modulator.carrier_freq_hz = 55e3

        # yappi.start()

        self.network_sdr_plugin_sender.send_raw_data(
            modulator.modulate(msg_a.encoded_bits), 1)
        QTest.qWait(10)
        # send some zeros to simulate the end of a message
        self.network_sdr_plugin_sender.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)
        QTest.qWait(100)
        receive_process.join(10)

        logger.info("PROCESS TIME: {0:.2f}ms".format(elapsed.value))

        self.assertEqual(current_index.value, target_num_samples)
        self.assertLess(elapsed.value, 200)

        # timeout = spy.wait(2000)
        # yappi.get_func_stats().print_all()
        # yappi.get_thread_stats().print_all()

    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(
            len(self.form.simulator_tab_controller.simulator_scene.
                get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(10)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)
        QTest.qWait(10)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(1500)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages()
                   if msg.source.name == "Alice")
        checksum_label = next(
            lbl for lbl in msg.message_type
            if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        QTest.qWait(50)
        self.assertTrue(simulator.simulation_is_finished())

        time.sleep(1)

        conn.close()
        s.close()

        QTest.qWait(100)

    def test_external_program_simulator(self):
        stc = self.form.simulator_tab_controller
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(
            action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        lbl1.value_type_index = 3
        lbl1.external_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str
        lbl2.value_type_index = 3
        lbl2.external_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str

        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        fname = tempfile.mktemp()
        self.assertFalse(os.path.isfile(fname))
        external_command = "cmd.exe /C copy NUL {}".format(
            fname) if os.name == "nt" else "touch {}".format(fname)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(10)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)
        QTest.qWait(10)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(1500)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42),
                                 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(bits[0], "101010101")

        QTest.qWait(500)
        self.assertTrue(simulator.simulation_is_finished())

        conn.close()
        s.close()

        QTest.qWait(100)

        self.assertTrue(os.path.isfile(fname))

    def __demodulate(self, connection):
        QTest.qWait(100)
        data = connection.recv(65536)
        while len(data) % 8 != 0:
            data += connection.recv(65536)

        arr = np.array(np.frombuffer(data, dtype=np.complex64))
        signal = Signal("", "")
        signal._fulldata = arr
        pa = ProtocolAnalyzer(signal)
        pa.get_protocol_from_signal()
        return pa.plain_bits_str
示例#10
0
    def test_external_program_simulator(self):
        stc = self.form.simulator_tab_controller
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(
            action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        lbl1.value_type_index = 3
        lbl1.external_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str
        lbl2.value_type_index = 3
        lbl2.external_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str

        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        fname = tempfile.mktemp()
        self.assertFalse(os.path.isfile(fname))
        external_command = "cmd.exe /C copy NUL {}".format(
            fname) if os.name == "nt" else "touch {}".format(fname)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(10)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)
        QTest.qWait(10)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(1500)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42),
                                 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(bits[0], "101010101")

        QTest.qWait(500)
        self.assertTrue(simulator.simulation_is_finished())

        conn.close()
        s.close()

        QTest.qWait(100)

        self.assertTrue(os.path.isfile(fname))
示例#11
0
    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(
            len(self.form.simulator_tab_controller.simulator_scene.
                get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(10)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)
        QTest.qWait(10)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(1500)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages()
                   if msg.source.name == "Alice")
        checksum_label = next(
            lbl for lbl in msg.message_type
            if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        self.alice.send_raw_data(
            np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        bits = self.__demodulate(conn)
        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        QTest.qWait(50)
        self.assertTrue(simulator.simulation_is_finished())

        time.sleep(1)

        conn.close()
        s.close()

        QTest.qWait(100)
示例#12
0
    def __init__(self, backend_handler, name: str, mode: Mode, freq=None, sample_rate=None, bandwidth=None,
                 gain=None, if_gain=None, baseband_gain=None,
                 samples_to_send=None,
                 device_ip=None, sending_repeats=1, parent=None, is_ringbuffer=False, raw_mode=True, portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent, is_ringbuffer=is_ringbuffer)
                self.__dev.index_changed.connect(self.emit_index_changed)
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send)
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                is_ringbuffer = self.mode == Mode.spectrum or is_ringbuffer

                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain, is_ringbuffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq, gain, sample_rate, device_number=0, is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq, gain, sample_rate, device_number=0, is_ringbuffer=is_ringbuffer)
                else:
                    raise NotImplementedError("Native Backend for {0} not yet implemented".format(name))
            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain, is_ringbuffer)
                self.__dev.BYTES_PER_SAMPLE = 4
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send, sending_repeats, skip_device_parameters=True)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(raw_mode=raw_mode, spectrum=self.mode == Mode.spectrum)
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")
示例#13
0
class TestProtocolSniffer(QtTestCase):
    def setUp(self):
        super().setUp()
        SettingsProxy.OVERWRITE_RECEIVE_BUFFER_SIZE = 100 * 10**6

    def test_protocol_sniffer(self):
        bit_len = 100
        center = 0.0942
        noise = 0.1
        tolerance = 2
        modulation_type = 1
        sample_rate = 1e6
        device_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        sniffer = ProtocolSniffer(bit_len=bit_len,
                                  center=center,
                                  noise=noise,
                                  tolerance=tolerance,
                                  modulation_type=modulation_type,
                                  device=device_name,
                                  backend_handler=BackendHandler(),
                                  network_raw_mode=True)

        port = self.get_free_port()
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(
            raw_mode=True)
        self.network_sdr_plugin_sender.client_port = port

        sniffer.sniff()
        QTest.qWait(10)

        data = ["101010", "000111", "1111000"]
        pause = 10 * bit_len
        modulator = Modulator("test")
        modulator.samples_per_bit = bit_len
        modulator.sample_rate = sample_rate
        modulator.modulation_type = modulation_type
        modulator.param_for_one = 20e3
        modulator.param_for_zero = 10e3

        packages = []
        for d in data:
            packages.append(modulator.modulate(list(map(int, d)), pause))

        # verify modulation was correct
        pa = ProtocolAnalyzer(None)
        signal = Signal("", "", sample_rate=sample_rate)
        signal._fulldata = np.concatenate(packages)
        signal.modulation_type = modulation_type
        signal.bit_len = bit_len
        signal.tolerance = tolerance
        signal.noise_threshold = noise
        signal.qad_center = center
        pa.signal = signal
        pa.get_protocol_from_signal()
        self.assertEqual(pa.plain_bits_str, data)

        # send data
        send_data = np.concatenate(packages)
        chunk_size = 128
        for i in range(0, len(send_data), chunk_size):
            self.network_sdr_plugin_sender.send_raw_data(
                send_data[i:i + chunk_size], 1)
            QTest.qWait(10)

        # Send enough pauses to end sniffing
        for i in range(10):
            self.network_sdr_plugin_sender.send_raw_data(
                np.zeros(bit_len, dtype=np.complex64), 1)
            QTest.qWait(10)

        sniffer.stop()
        self.assertEqual(sniffer.plain_bits_str, data)

        # needed to prevent crash on windows
        QTest.qWait(10)
示例#14
0
    def test_open_simulator_dialog_and_send_mismatching_message(self):
        def __wait_for_simulator_log_message(dialog, log_message):

            n = 0
            while not any(log_message in msg
                          for msg in dialog.simulator.log_messages):
                if n < 50:
                    time.sleep(0.5)
                else:
                    self.fail("Did not receive log message \"{}\"".format(
                        log_message))
                n += 1

        stc = self.form.simulator_tab_controller
        assert isinstance(stc, SimulatorTabController)

        self.__setup_project()
        self.add_all_signals_to_simulator()

        stc.simulator_scene.select_all_items()
        stc.simulator_config.project_manager.simulator_timeout_ms = 999999999

        for msg in stc.simulator_scene.get_selected_messages():
            msg.destination = self.dennis
            stc.ui.gvSimulator.message_updated.emit(msg)

        list_model = stc.ui.listViewSimulate.model()
        self.assertEqual(list_model.rowCount(), 2)
        list_model.setData(list_model.createIndex(1, 0),
                           Qt.Checked,
                           role=Qt.CheckStateRole)

        dialog = stc.get_simulator_dialog()

        network_sdr_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(
            network_sdr_name)

        rcv_port = util.get_free_port()
        dialog.simulator.sniffer.rcv_device.set_server_port(rcv_port)

        dialog.simulator.sniffer.adaptive_noise = False
        dialog.simulator.sniffer.automatic_center = False

        dialog.ui.btnStartStop.click()

        __wait_for_simulator_log_message(dialog, "Waiting for message 1")

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        sender = NetworkSDRInterfacePlugin(raw_mode=True, sending=True)
        sender.client_port = rcv_port

        sender.send_raw_data(modulator.modulate("1" * 352), 1)
        time.sleep(0.5)
        sender.send_raw_data(IQArray(None, np.float32, 2000), 1)

        __wait_for_simulator_log_message(dialog, "Waiting for message 2")

        sender.send_raw_data(modulator.modulate("10" * 176), 1)
        time.sleep(0.5)
        sender.send_raw_data(IQArray(None, np.float32, 2000), 1)
        __wait_for_simulator_log_message(dialog, "Mismatch for label:")

        dialog.on_timer_timeout()  # enforce writing to text view
        simulator_log = dialog.ui.textEditSimulation.toPlainText()
        self.assertIn("Received message 1", simulator_log)
        self.assertIn("preamble: 11111111", simulator_log)
        self.assertIn("Mismatch for label: preamble", simulator_log)

        dialog.close()
示例#15
0
class GeneratorTabController(QWidget):
    def __init__(self, compare_frame_controller: CompareFrameController, project_manager: ProjectManager, parent=None):
        super().__init__(parent)
        self.ui = Ui_GeneratorTab()
        self.ui.setupUi(self)
        util.set_splitter_stylesheet(self.ui.splitter)

        self.project_manager = project_manager

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = GeneratorTreeModel(compare_frame_controller)
        self.tree_model.set_root_item(compare_frame_controller.proto_tree_model.rootItem)
        self.tree_model.controller = self
        self.ui.treeProtocols.setModel(self.tree_model)

        self.table_model = GeneratorTableModel(compare_frame_controller.proto_tree_model.rootItem,
                                               compare_frame_controller.decodings)
        self.table_model.controller = self
        self.ui.tableMessages.setModel(self.table_model)

        self.label_list_model = GeneratorListModel(None)
        self.ui.listViewProtoLabels.setModel(self.label_list_model)

        self.network_sdr_button_orig_tooltip = self.ui.btnNetworkSDRSend.toolTip()
        self.set_network_sdr_send_button_visibility()
        self.set_rfcat_button_visibility()
        self.network_sdr_plugin = NetworkSDRInterfacePlugin()
        self.rfcat_plugin = RfCatPlugin()
        self.init_rfcat_plugin()

        self.modulation_msg_indices = []

        self.refresh_modulators()
        self.on_selected_modulation_changed()
        self.set_fuzzing_ui_status()
        self.ui.prBarGeneration.hide()
        self.create_connects(compare_frame_controller)

        self.set_modulation_profile_status()

    def __get_modulator_of_message(self, message: Message) -> Modulator:
        if message.modulator_index > len(self.modulators) - 1:
            message.modulator_index = 0
        return self.modulators[message.modulator_index]

    @property
    def selected_message_index(self) -> int:
        min_row, _, _, _ = self.ui.tableMessages.selection_range()
        return min_row  #

    @property
    def selected_message(self) -> Message:
        selected_msg_index = self.selected_message_index
        if selected_msg_index == -1 or selected_msg_index >= len(self.table_model.protocol.messages):
            return None

        return self.table_model.protocol.messages[selected_msg_index]

    @property
    def active_groups(self):
        return self.tree_model.groups

    @property
    def modulators(self):
        return self.project_manager.modulators

    @property
    def total_modulated_samples(self) -> int:
        return sum(int(len(msg.encoded_bits) * self.__get_modulator_of_message(msg).samples_per_bit + msg.pause)
                   for msg in self.table_model.protocol.messages)

    @modulators.setter
    def modulators(self, value):
        assert type(value) == list
        self.project_manager.modulators = value

    def create_connects(self, compare_frame_controller):
        compare_frame_controller.proto_tree_model.modelReset.connect(self.refresh_tree)
        compare_frame_controller.participant_changed.connect(self.table_model.refresh_vertical_header)
        self.ui.btnEditModulation.clicked.connect(self.show_modulation_dialog)
        self.ui.cBoxModulations.currentIndexChanged.connect(self.on_selected_modulation_changed)
        self.ui.tableMessages.selectionModel().selectionChanged.connect(self.on_table_selection_changed)
        self.ui.tableMessages.encodings_updated.connect(self.on_table_selection_changed)
        self.table_model.undo_stack.indexChanged.connect(self.on_undo_stack_index_changed)
        self.table_model.protocol.qt_signals.line_duplicated.connect(self.refresh_pause_list)
        self.table_model.protocol.qt_signals.fuzzing_started.connect(self.on_fuzzing_started)
        self.table_model.protocol.qt_signals.current_fuzzing_message_changed.connect(
            self.on_current_fuzzing_message_changed)
        self.table_model.protocol.qt_signals.fuzzing_finished.connect(self.on_fuzzing_finished)
        self.table_model.first_protocol_added.connect(self.on_first_protocol_added)
        self.label_list_model.protolabel_fuzzing_status_changed.connect(self.set_fuzzing_ui_status)
        self.ui.cbViewType.currentIndexChanged.connect(self.on_view_type_changed)
        self.ui.btnSend.clicked.connect(self.on_btn_send_clicked)
        self.ui.btnSave.clicked.connect(self.on_btn_save_clicked)
        self.ui.btnOpen.clicked.connect(self.on_btn_open_clicked)

        self.project_manager.project_updated.connect(self.on_project_updated)

        self.table_model.vertical_header_color_status_changed.connect(
            self.ui.tableMessages.on_vertical_header_color_status_changed)

        self.label_list_model.protolabel_removed.connect(self.handle_proto_label_removed)

        self.ui.lWPauses.item_edit_clicked.connect(self.edit_pause_item)
        self.ui.lWPauses.edit_all_items_clicked.connect(self.edit_all_pause_items)
        self.ui.lWPauses.itemSelectionChanged.connect(self.on_lWpauses_selection_changed)
        self.ui.lWPauses.lost_focus.connect(self.on_lWPauses_lost_focus)
        self.ui.lWPauses.doubleClicked.connect(self.on_lWPauses_double_clicked)
        self.ui.btnGenerate.clicked.connect(self.generate_file)
        self.label_list_model.protolabel_fuzzing_status_changed.connect(self.handle_plabel_fuzzing_state_changed)
        self.ui.btnFuzz.clicked.connect(self.on_btn_fuzzing_clicked)
        self.ui.tableMessages.create_label_triggered.connect(self.create_fuzzing_label)
        self.ui.tableMessages.edit_label_triggered.connect(self.show_fuzzing_dialog)
        self.ui.listViewProtoLabels.selection_changed.connect(self.handle_label_selection_changed)
        self.ui.listViewProtoLabels.edit_on_item_triggered.connect(self.show_fuzzing_dialog)

        self.ui.btnNetworkSDRSend.clicked.connect(self.on_btn_network_sdr_clicked)
        self.ui.btnRfCatSend.clicked.connect(self.on_btn_rfcat_clicked)

        self.network_sdr_plugin.sending_status_changed.connect(self.on_network_sdr_sending_status_changed)
        self.network_sdr_plugin.sending_stop_requested.connect(self.on_network_sdr_sending_stop_requested)
        self.network_sdr_plugin.current_send_message_changed.connect(self.on_send_message_changed)

    @pyqtSlot()
    def refresh_tree(self):
        self.tree_model.beginResetModel()
        self.tree_model.endResetModel()
        self.ui.treeProtocols.expandAll()

    @pyqtSlot()
    def refresh_table(self):
        self.table_model.update()
        self.ui.tableMessages.resize_columns()
        is_data_there = self.table_model.display_data is not None and len(self.table_model.display_data) > 0
        self.ui.btnSend.setEnabled(is_data_there)
        self.ui.btnGenerate.setEnabled(is_data_there)

    @pyqtSlot()
    def refresh_label_list(self):
        self.label_list_model.message = self.selected_message
        self.label_list_model.update()

    @property
    def generator_undo_stack(self) -> QUndoStack:
        return self.table_model.undo_stack

    @pyqtSlot()
    def on_selected_modulation_changed(self):
        cur_ind = self.ui.cBoxModulations.currentIndex()
        min_row, max_row, _, _ = self.ui.tableMessages.selection_range()
        if min_row > -1:
            # set modulation for selected messages
            for row in range(min_row, max_row + 1):
                try:
                    self.table_model.protocol.messages[row].modulator_index = cur_ind
                except IndexError:
                    continue

        self.show_modulation_info()

    def refresh_modulators(self):
        current_index = 0
        if type(self.sender()) == ModulatorDialog:
            current_index = self.sender().ui.comboBoxCustomModulations.currentIndex()
        self.ui.cBoxModulations.clear()
        for modulator in self.modulators:
            self.ui.cBoxModulations.addItem(modulator.name)

        self.ui.cBoxModulations.setCurrentIndex(current_index)

    def bootstrap_modulator(self, protocol: ProtocolAnalyzer):
        """
        Set initial parameters for default modulator if it was not edited by user previously
        :return:
        """
        if len(self.modulators) != 1 or len(self.table_model.protocol.messages) == 0:
            return

        modulator = self.modulators[0]
        modulator.samples_per_bit = protocol.messages[0].bit_len

        if protocol.signal:
            modulator.sample_rate = protocol.signal.sample_rate
            modulator.modulation_type = protocol.signal.modulation_type
            auto_freq = modulator.estimate_carrier_frequency(protocol.signal, protocol)
            if auto_freq is not None and auto_freq != 0:
                modulator.carrier_freq_hz = auto_freq

        self.show_modulation_info()

    def show_modulation_info(self):
        cur_ind = self.ui.cBoxModulations.currentIndex()
        cur_mod = self.modulators[cur_ind]
        self.ui.lCarrierFreqValue.setText(cur_mod.carrier_frequency_str)
        self.ui.lCarrierPhaseValue.setText(cur_mod.carrier_phase_str)
        self.ui.lBitLenValue.setText(cur_mod.bit_len_str)
        self.ui.lSampleRateValue.setText(cur_mod.sample_rate_str)
        mod_type = cur_mod.modulation_type_str
        self.ui.lModTypeValue.setText(mod_type)
        if mod_type == "ASK":
            prefix = "Amplitude"
        elif mod_type == "PSK":
            prefix = "Phase"
        elif mod_type in ("FSK", "GFSK"):
            prefix = "Frequency"
        else:
            prefix = "Unknown Modulation Type (This should not happen...)"

        self.ui.lParamForZero.setText(prefix + " for 0:")
        self.ui.lParamForZeroValue.setText(cur_mod.param_for_zero_str)
        self.ui.lParamForOne.setText(prefix + " for 1:")
        self.ui.lParamForOneValue.setText(cur_mod.param_for_one_str)

    def prepare_modulation_dialog(self) -> (ModulatorDialog, Message):
        preselected_index = self.ui.cBoxModulations.currentIndex()

        min_row, max_row, start, end = self.ui.tableMessages.selection_range()
        if min_row > -1:
            try:
                selected_message = self.table_model.protocol.messages[min_row]
                preselected_index = selected_message.modulator_index
            except IndexError:
                selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0], 0, [], MessageType("empty"))
        else:
            selected_message = Message([1, 0, 1, 0, 1, 0, 1, 0], 0, [], MessageType("empty"))
            if len(self.table_model.protocol.messages) > 0:
                selected_message.bit_len = self.table_model.protocol.messages[0].bit_len

        for m in self.modulators:
            m.default_sample_rate = self.project_manager.device_conf["sample_rate"]

        modulator_dialog = ModulatorDialog(self.modulators, tree_model=self.tree_model, parent=self.parent())
        modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex(preselected_index)

        modulator_dialog.finished.connect(self.refresh_modulators)
        modulator_dialog.finished.connect(self.refresh_pause_list)

        return modulator_dialog, selected_message

    def set_modulation_profile_status(self):
        visible = constants.SETTINGS.value("multiple_modulations", False, bool)
        self.ui.cBoxModulations.setVisible(visible)

    def init_rfcat_plugin(self):
        self.set_rfcat_button_visibility()
        self.rfcat_plugin = RfCatPlugin()
        self.rfcat_plugin.current_send_message_changed.connect(self.on_send_message_changed)
        self.ui.btnRfCatSend.setEnabled(self.rfcat_plugin.rfcat_is_found)

    @pyqtSlot()
    def on_undo_stack_index_changed(self):
        self.refresh_table()
        self.refresh_pause_list()
        self.refresh_label_list()
        self.refresh_estimated_time()
        self.set_fuzzing_ui_status()

    @pyqtSlot()
    def show_modulation_dialog(self):
        modulator_dialog, message = self.prepare_modulation_dialog()
        modulator_dialog.showMaximized()

        modulator_dialog.initialize(message.encoded_bits_str[0:10])
        self.project_manager.modulation_was_edited = True

    @pyqtSlot()
    def on_table_selection_changed(self):
        min_row, max_row, start, end = self.ui.tableMessages.selection_range()

        if min_row == -1:
            self.ui.lEncodingValue.setText("-")  #
            self.ui.lEncodingValue.setToolTip("")
            self.label_list_model.message = None
            return

        container = self.table_model.protocol
        message = container.messages[min_row]
        self.label_list_model.message = message
        decoder_name = message.decoder.name
        metrics = QFontMetrics(self.ui.lEncodingValue.font())
        elidedName = metrics.elidedText(decoder_name, Qt.ElideRight, self.ui.lEncodingValue.width())
        self.ui.lEncodingValue.setText(elidedName)
        self.ui.lEncodingValue.setToolTip(decoder_name)
        self.ui.cBoxModulations.blockSignals(True)
        self.ui.cBoxModulations.setCurrentIndex(message.modulator_index)
        self.show_modulation_info()
        self.ui.cBoxModulations.blockSignals(False)

    @pyqtSlot(int)
    def edit_pause_item(self, index: int):
        message = self.table_model.protocol.messages[index]
        cur_len = message.pause
        new_len, ok = QInputDialog.getInt(self, self.tr("Enter new Pause Length"),
                                          self.tr("Pause Length:"), cur_len, 0)
        if ok:
            message.pause = new_len
            self.refresh_pause_list()

    @pyqtSlot()
    def edit_all_pause_items(self):
        message = self.table_model.protocol.messages[0]
        cur_len = message.pause
        new_len, ok = QInputDialog.getInt(self, self.tr("Enter new Pause Length"),
                                          self.tr("Pause Length:"), cur_len, 0)
        if ok:
            for message in self.table_model.protocol.messages:
                message.pause = new_len

            self.refresh_pause_list()

    @pyqtSlot()
    def on_lWPauses_double_clicked(self):
        sel_indexes = [index.row() for index in self.ui.lWPauses.selectedIndexes()]
        if len(sel_indexes) > 0:
            self.edit_pause_item(sel_indexes[0])

    @pyqtSlot()
    def refresh_pause_list(self):
        self.ui.lWPauses.clear()

        fmt_str = "Pause ({1:d}-{2:d}) <{0:d} samples ({3})>"
        for i, pause in enumerate(self.table_model.protocol.pauses):
            sr = self.__get_modulator_of_message(self.table_model.protocol.messages[i]).sample_rate
            item = fmt_str.format(pause, i + 1, i + 2, Formatter.science_time(pause / sr))
            self.ui.lWPauses.addItem(item)

        self.refresh_estimated_time()

    @pyqtSlot()
    def on_lWpauses_selection_changed(self):
        rows = [index.row() for index in self.ui.lWPauses.selectedIndexes()]
        if len(rows) == 0:
            return
        self.ui.tableMessages.show_pause_active = True
        self.ui.tableMessages.pause_row = rows[0]
        self.ui.tableMessages.viewport().update()
        self.ui.tableMessages.scrollTo(self.table_model.index(rows[0], 0))

    @pyqtSlot()
    def on_lWPauses_lost_focus(self):
        self.ui.tableMessages.show_pause_active = False
        self.ui.tableMessages.viewport().update()

    @pyqtSlot()
    def generate_file(self):
        try:
            total_samples = self.total_modulated_samples
            buffer = self.prepare_modulation_buffer(total_samples, show_error=False)
            if buffer is None:
                Errors.generic_error(self.tr("File too big"), self.tr("This file would get too big to save."))
                self.unsetCursor()
                return
            modulated_samples = self.modulate_data(buffer)
            try:
                sample_rate = self.modulators[0].sample_rate
            except Exception as e:
                logger.exception(e)
                sample_rate = 1e6
            FileOperator.save_data_dialog("generated.complex", modulated_samples, sample_rate=sample_rate, parent=self)
        except Exception as e:
            Errors.generic_error(self.tr("Failed to generate data"), str(e), traceback.format_exc())
            self.unsetCursor()

    def prepare_modulation_buffer(self, total_samples: int, show_error=True) -> np.ndarray:
        memory_size_for_buffer = total_samples * 8
        logger.debug("Allocating {0:.2f}MB for modulated samples".format(memory_size_for_buffer / (1024 ** 2)))
        try:
            # allocate it three times as we need the same amount for the sending process
            np.zeros(3*total_samples, dtype=np.complex64)
        except MemoryError:
            # will go into continuous mode in this case
            if show_error:
                Errors.not_enough_ram_for_sending_precache(3*memory_size_for_buffer)
            return None

        return np.zeros(total_samples, dtype=np.complex64)

    def modulate_data(self, buffer: np.ndarray) -> np.ndarray:
        """
        
        :param buffer: Buffer in which the modulated data shall be written, initialized with zeros
        :return: 
        """
        self.ui.prBarGeneration.show()
        self.ui.prBarGeneration.setValue(0)
        self.ui.prBarGeneration.setMaximum(self.table_model.row_count)
        self.modulation_msg_indices.clear()

        pos = 0
        for i in range(0, self.table_model.row_count):
            message = self.table_model.protocol.messages[i]
            modulator = self.__get_modulator_of_message(message)
            # We do not need to modulate the pause extra, as result is already initialized with zeros
            modulated = modulator.modulate(start=0, data=message.encoded_bits, pause=0)
            buffer[pos:pos + len(modulated)] = modulated
            pos += len(modulated) + message.pause
            self.modulation_msg_indices.append(pos)
            self.ui.prBarGeneration.setValue(i + 1)
            QApplication.instance().processEvents()

        self.ui.prBarGeneration.hide()
        return buffer

    @pyqtSlot(int)
    def show_fuzzing_dialog(self, label_index: int):
        view = self.ui.cbViewType.currentIndex()

        if self.label_list_model.message is not None:
            msg_index = self.table_model.protocol.messages.index(self.label_list_model.message)
            fdc = FuzzingDialog(protocol=self.table_model.protocol, label_index=label_index,
                                msg_index=msg_index, proto_view=view, parent=self)
            fdc.show()
            fdc.finished.connect(self.refresh_label_list)
            fdc.finished.connect(self.refresh_table)
            fdc.finished.connect(self.set_fuzzing_ui_status)

    @pyqtSlot()
    def handle_plabel_fuzzing_state_changed(self):
        self.refresh_table()
        self.label_list_model.update()

    @pyqtSlot(ProtocolLabel)
    def handle_proto_label_removed(self, plabel: ProtocolLabel):
        self.refresh_label_list()
        self.refresh_table()
        self.set_fuzzing_ui_status()

    @pyqtSlot()
    def on_btn_fuzzing_clicked(self):
        fuz_mode = "Successive"
        if self.ui.rbConcurrent.isChecked():
            fuz_mode = "Concurrent"
        elif self.ui.rBExhaustive.isChecked():
            fuz_mode = "Exhaustive"

        self.setCursor(Qt.WaitCursor)
        fuzz_action = Fuzz(self.table_model.protocol, fuz_mode)
        self.table_model.undo_stack.push(fuzz_action)
        for row in fuzz_action.added_message_indices:
            self.table_model.update_checksums_for_row(row)
        self.unsetCursor()
        self.ui.tableMessages.setFocus()

    @pyqtSlot()
    def set_fuzzing_ui_status(self):
        btn_was_enabled = self.ui.btnFuzz.isEnabled()
        fuzz_active = any(lbl.active_fuzzing for msg in self.table_model.protocol.messages for lbl in msg.message_type)
        self.ui.btnFuzz.setEnabled(fuzz_active)
        if self.ui.btnFuzz.isEnabled() and not btn_was_enabled:
            font = self.ui.btnFuzz.font()
            font.setBold(True)
            self.ui.btnFuzz.setFont(font)
        else:
            font = self.ui.btnFuzz.font()
            font.setBold(False)
            self.ui.btnFuzz.setFont(font)
            self.ui.btnFuzz.setStyleSheet("")

        has_same_message = self.table_model.protocol.multiple_fuzz_labels_per_message
        self.ui.rBSuccessive.setEnabled(has_same_message)
        self.ui.rBExhaustive.setEnabled(has_same_message)
        self.ui.rbConcurrent.setEnabled(has_same_message)

    def refresh_existing_encodings(self, encodings_from_file):
        """
        Refresh existing encodings for messages, when encoding was changed by user in dialog

        :return:
        """
        update = False

        for msg in self.table_model.protocol.messages:
            i = next((i for i, d in enumerate(encodings_from_file) if d.name == msg.decoder.name), 0)
            if msg.decoder != encodings_from_file[i]:
                update = True
                msg.decoder = encodings_from_file[i]
                msg.clear_decoded_bits()
                msg.clear_encoded_bits()

        if update:
            self.refresh_table()
            self.refresh_estimated_time()

    @pyqtSlot()
    def refresh_estimated_time(self):
        c = self.table_model.protocol
        if c.num_messages == 0:
            self.ui.lEstimatedTime.setText("Estimated Time: ")
            return

        avg_msg_len = numpy.mean([len(msg.encoded_bits) for msg in c.messages])
        avg_bit_len = numpy.mean([m.samples_per_bit for m in self.modulators])
        avg_sample_rate = numpy.mean([m.sample_rate for m in self.modulators])
        pause_samples = sum(c.pauses)
        nsamples = c.num_messages * avg_msg_len * avg_bit_len + pause_samples

        self.ui.lEstimatedTime.setText(
            locale.format_string("Estimated Time: %.04f seconds", nsamples / avg_sample_rate))

    @pyqtSlot(int, int, int)
    def create_fuzzing_label(self, msg_index: int, start: int, end: int):
        con = self.table_model.protocol
        start, end = con.convert_range(start, end - 1, self.ui.cbViewType.currentIndex(), 0, False, msg_index)
        lbl = con.create_fuzzing_label(start, end, msg_index)
        self.show_fuzzing_dialog(con.protocol_labels.index(lbl))

    @pyqtSlot()
    def handle_label_selection_changed(self):
        rows = [index.row() for index in self.ui.listViewProtoLabels.selectedIndexes()]
        if len(rows) == 0:
            return

        maxrow = numpy.max(rows)

        try:
            label = self.table_model.protocol.protocol_labels[maxrow]
        except IndexError:
            return
        if label.show and self.selected_message:
            start, end = self.selected_message.get_label_range(lbl=label, view=self.table_model.proto_view,
                                                               decode=False)
            indx = self.table_model.index(0, int((start + end) / 2))
            self.ui.tableMessages.scrollTo(indx)

    @pyqtSlot()
    def on_view_type_changed(self):
        self.setCursor(Qt.WaitCursor)
        self.table_model.proto_view = self.ui.cbViewType.currentIndex()
        self.ui.tableMessages.resize_columns()
        self.unsetCursor()

    @pyqtSlot()
    def on_btn_send_clicked(self):
        try:
            total_samples = self.total_modulated_samples
            buffer = self.prepare_modulation_buffer(total_samples)
            if buffer is not None:
                modulated_data = self.modulate_data(buffer)
            else:
                # Enter continuous mode
                modulated_data = None

            try:
                if modulated_data is not None:
                    try:
                        dialog = SendDialog(self.project_manager, modulated_data=modulated_data,
                                            modulation_msg_indices=self.modulation_msg_indices, parent=self)
                    except MemoryError:
                        # Not enough memory for device buffer so we need to create a continuous send dialog
                        del modulated_data
                        Errors.not_enough_ram_for_sending_precache(None)
                        dialog = ContinuousSendDialog(self.project_manager,
                                                      self.table_model.protocol.messages,
                                                      self.modulators, total_samples, parent=self)
                else:
                    dialog = ContinuousSendDialog(self.project_manager, self.table_model.protocol.messages,
                                                  self.modulators, total_samples, parent=self)
            except OSError as e:
                logger.exception(e)
                return
            if dialog.has_empty_device_list:
                Errors.no_device()
                dialog.close()
                return

            dialog.device_parameters_changed.connect(self.project_manager.set_device_parameters)
            dialog.show()
            dialog.graphics_view.show_full_scene(reinitialize=True)
        except Exception as e:
            Errors.generic_error(self.tr("Failed to generate data"), str(e), traceback.format_exc())
            self.unsetCursor()

    @pyqtSlot()
    def on_btn_save_clicked(self):
        filename = FileOperator.get_save_file_name("profile.fuzz.xml", caption="Save fuzz profile")
        if filename:
            self.table_model.protocol.to_xml_file(filename,
                                                  decoders=self.project_manager.decodings,
                                                  participants=self.project_manager.participants,
                                                  modulators=self.modulators)

    @pyqtSlot()
    def on_btn_open_clicked(self):
        dialog = FileOperator.get_open_dialog(directory_mode=False, parent=self, name_filter="fuzz")
        if dialog.exec_():
            for filename in dialog.selectedFiles():
                self.load_from_file(filename)

    def load_from_file(self, filename: str):
        try:
            self.modulators = ProjectManager.read_modulators_from_file(filename)
            self.table_model.protocol.from_xml_file(filename)
            self.refresh_pause_list()
            self.refresh_estimated_time()
            self.refresh_modulators()
            self.show_modulation_info()
            self.refresh_table()
            self.set_fuzzing_ui_status()
        except:
            logger.error("You done something wrong to the xml fuzzing profile.")

    @pyqtSlot()
    def on_project_updated(self):
        self.table_model.refresh_vertical_header()

    def set_network_sdr_send_button_visibility(self):
        is_plugin_enabled = PluginManager().is_plugin_enabled("NetworkSDRInterface")
        self.ui.btnNetworkSDRSend.setVisible(is_plugin_enabled)

    def set_rfcat_button_visibility(self):
        is_plugin_enabled = PluginManager().is_plugin_enabled("RfCat")
        self.ui.btnRfCatSend.setVisible(is_plugin_enabled)

    @pyqtSlot()
    def on_btn_network_sdr_clicked(self):
        if not self.network_sdr_plugin.is_sending:
            messages = self.table_model.protocol.messages
            sample_rates = [self.__get_modulator_of_message(msg).sample_rate for msg in messages]
            self.network_sdr_plugin.start_message_sending_thread(messages, sample_rates)
        else:
            self.network_sdr_plugin.stop_sending_thread()

    @pyqtSlot(bool)
    def on_network_sdr_sending_status_changed(self, is_sending: bool):
        self.ui.btnNetworkSDRSend.setChecked(is_sending)
        self.ui.btnNetworkSDRSend.setEnabled(True)
        self.ui.btnNetworkSDRSend.setToolTip(
            "Sending in progress" if is_sending else self.network_sdr_button_orig_tooltip)
        if not is_sending:
            self.ui.tableMessages.clearSelection()

    @pyqtSlot()
    def on_network_sdr_sending_stop_requested(self):
        self.ui.btnNetworkSDRSend.setToolTip("Stopping sending")
        self.ui.btnNetworkSDRSend.setEnabled(False)

    @pyqtSlot(int)
    def on_send_message_changed(self, message_index: int):
        self.ui.tableMessages.selectRow(message_index)

    @pyqtSlot()
    def on_btn_rfcat_clicked(self):
        if not self.rfcat_plugin.is_sending:
            messages = self.table_model.protocol.messages
            sample_rates = [self.__get_modulator_of_message(msg).sample_rate for msg in messages]
            self.rfcat_plugin.start_message_sending_thread(messages, sample_rates, self.modulators,
                                                           self.project_manager)
        else:
            self.rfcat_plugin.stop_sending_thread()

    @pyqtSlot(int)
    def on_fuzzing_started(self, num_values: int):
        self.ui.stackedWidgetFuzzing.setCurrentWidget(self.ui.pageFuzzingProgressBar)
        self.ui.progressBarFuzzing.setMaximum(num_values)
        self.ui.progressBarFuzzing.setValue(0)
        QApplication.instance().processEvents()

    @pyqtSlot()
    def on_fuzzing_finished(self):
        self.ui.stackedWidgetFuzzing.setCurrentWidget(self.ui.pageFuzzingUI)
        # Calculate Checksums for Fuzzed Messages
        self.setCursor(Qt.WaitCursor)

        self.unsetCursor()

    @pyqtSlot(int)
    def on_current_fuzzing_message_changed(self, current_message: int):
        self.ui.progressBarFuzzing.setValue(current_message)
        QApplication.instance().processEvents()

    @pyqtSlot(ProtocolAnalyzer)
    def on_first_protocol_added(self, protocol: ProtocolAnalyzer):
        if not self.project_manager.modulation_was_edited:
            self.bootstrap_modulator(protocol)
示例#16
0
class TestSimulator(QtTestCase):
    TIMEOUT = 0.5

    def setUp(self):
        super().setUp()
        SettingsProxy.OVERWRITE_RECEIVE_BUFFER_SIZE = 50000

        self.num_zeros_for_pause = 1000

    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(len(self.form.simulator_tab_controller.simulator_scene.get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog()  # type: SimulatorDialog
        dialog.project_manager.simulator_timeout_ms = 999999999

        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(250)

        while not any("Waiting for message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(1)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages() if msg.source.name == "Alice")
        checksum_label = next(lbl for lbl in msg.message_type if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 2" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 2")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str), msg=bits)
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 4" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 4")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 6" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 6")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)

        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

    def test_external_program_simulator(self):
        stc = self.form.simulator_tab_controller  # type: SimulatorTabController
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.project_manager.simulator_timeout_ms = 999999999

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items() if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        ext_program = get_path_for_data_file("external_program_simulator.py") + " " + counter_item_str
        if sys.platform == "win32":
            ext_program = sys.executable + " " + ext_program

        lbl1.value_type_index = 3
        lbl1.external_program = ext_program
        lbl2.value_type_index = 3
        lbl2.external_program = ext_program

        action = next(item for item in stc.simulator_scene.items() if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.000000001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items() if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        file_name = os.path.join(tempfile.gettempdir(), "external_test")
        if os.path.isfile(file_name):
            os.remove(file_name)

        self.assertFalse(os.path.isfile(file_name))
        external_command = "cmd.exe /C copy NUL {}".format(file_name) if os.name == "nt" else "touch {}".format(file_name)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(100)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(250)

        while not any("Waiting for message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(1)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message")
            time.sleep(1)

        time.sleep(self.TIMEOUT)
        bits = self.__demodulate(conn)
        self.assertEqual(bits[0].rstrip("0"), "101010101")

        while simulator.is_simulating:
            logger.debug("Wait for simulator to finish")
            time.sleep(1)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

        self.assertTrue(os.path.isfile(file_name))

    def __demodulate(self, connection: socket.socket):
        connection.settimeout(0.1)
        time.sleep(self.TIMEOUT)

        total_data = []
        while True:
            try:
                data = connection.recv(65536)
                if data:
                    total_data.append(data)
                else:
                    break
            except socket.timeout:
                break

        if len(total_data) == 0:
            logger.error("Did not receive any data from socket.")

        arr = np.array(np.frombuffer(b"".join(total_data), dtype=np.complex64))
        signal = Signal("", "")
        signal._fulldata = arr
        pa = ProtocolAnalyzer(signal)
        pa.get_protocol_from_signal()
        return pa.plain_bits_str
示例#17
0
    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(len(self.form.simulator_tab_controller.simulator_scene.get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog()  # type: SimulatorDialog
        dialog.project_manager.simulator_timeout_ms = 999999999

        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(250)

        while not any("Waiting for message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(1)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages() if msg.source.name == "Alice")
        checksum_label = next(lbl for lbl in msg.message_type if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 2" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 2")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str), msg=bits)
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 4" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 4")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message 6" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 6")
            time.sleep(1)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)

        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)
示例#18
0
    def test_external_program_simulator(self):
        stc = self.form.simulator_tab_controller  # type: SimulatorTabController
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.project_manager.simulator_timeout_ms = 999999999

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items() if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        ext_program = get_path_for_data_file("external_program_simulator.py") + " " + counter_item_str
        if sys.platform == "win32":
            ext_program = sys.executable + " " + ext_program

        lbl1.value_type_index = 3
        lbl1.external_program = ext_program
        lbl2.value_type_index = 3
        lbl2.external_program = ext_program

        action = next(item for item in stc.simulator_scene.items() if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.000000001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items() if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        file_name = os.path.join(tempfile.gettempdir(), "external_test")
        if os.path.isfile(file_name):
            os.remove(file_name)

        self.assertFalse(os.path.isfile(file_name))
        external_command = "cmd.exe /C copy NUL {}".format(file_name) if os.name == "nt" else "touch {}".format(file_name)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        QTest.qWait(100)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()
        QTest.qWait(250)

        while not any("Waiting for message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(1)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)

        while not any("Sending message" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message")
            time.sleep(1)

        time.sleep(self.TIMEOUT)
        bits = self.__demodulate(conn)
        self.assertEqual(bits[0].rstrip("0"), "101010101")

        while simulator.is_simulating:
            logger.debug("Wait for simulator to finish")
            time.sleep(1)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

        self.assertTrue(os.path.isfile(file_name))
示例#19
0
    def test_performance(self):
        self.form = MainController()
        self.cfc = self.form.compare_frame_controller
        self.stc = self.form.simulator_tab_controller
        self.gtc = self.form.generator_tab_controller

        self.form.add_signalfile(get_path_for_data_file("esaver.coco"))
        self.sframe = self.form.signal_tab_controller.signal_frames[0]
        self.sim_frame = self.form.simulator_tab_controller
        self.form.ui.tabWidget.setCurrentIndex(3)
        self.cfc.proto_analyzer.auto_assign_labels()

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True)

        part_a = Participant("Device A", shortname="A", color_index=0)
        part_b = Participant("Device B", shortname="B", color_index=1)
        part_b.simulate = True

        self.form.project_manager.participants.append(part_a)
        self.form.project_manager.participants.append(part_b)
        self.form.project_manager.project_updated.emit()

        sniffer = ProtocolSniffer(100, 0.01, 0.1, 5, 1, NetworkSDRInterfacePlugin.NETWORK_SDR_NAME, BackendHandler(),
                                  network_raw_mode=True)
        sender = EndlessSender(BackendHandler(), NetworkSDRInterfacePlugin.NETWORK_SDR_NAME)

        simulator = Simulator(self.stc.simulator_config, self.gtc.modulators, self.stc.sim_expression_parser,
                              self.form.project_manager, sniffer=sniffer, sender=sender)

        pause = 100
        msg_a = SimulatorMessage(part_b,
                                 [1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 pause=pause, message_type=MessageType("empty_message_type"), source=part_a)

        msg_b = SimulatorMessage(part_a,
                                 [1, 0] * 16 + [1, 1, 0, 0] * 8 + [1, 1, 0, 0] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 pause=pause, message_type=MessageType("empty_message_type"), source=part_b)

        self.stc.simulator_config.add_items([msg_a, msg_b], 0, None)
        self.stc.simulator_config.update_active_participants()

        port = self.get_free_port()
        sniffer = simulator.sniffer
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender.client_port = port

        sender = simulator.sender
        port = self.get_free_port()
        sender.device.set_client_port(port)
        sender.device._VirtualDevice__dev.name = "simulator_sender"

        current_index = Value("L")
        elapsed = Value("f")
        target_num_samples = 13600 + pause
        receive_process = Process(target=receive, args=(port, current_index, target_num_samples, elapsed))
        receive_process.daemon = True
        receive_process.start()

        # Ensure receiver is running
        time.sleep(2)

        # spy = QSignalSpy(self.network_sdr_plugin_receiver.rcv_index_changed)
        simulator.start()

        modulator = Modulator("test_modulator")
        modulator.samples_per_bit = 100
        modulator.carrier_freq_hz = 55e3

        # yappi.start()

        self.network_sdr_plugin_sender.send_raw_data(modulator.modulate(msg_a.encoded_bits), 1)
        time.sleep(0.5)
        # send some zeros to simulate the end of a message
        self.network_sdr_plugin_sender.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)
        time.sleep(0.5)
        receive_process.join(15)

        logger.info("PROCESS TIME: {0:.2f}ms".format(elapsed.value))

        # self.assertEqual(current_index.value, target_num_samples)
        self.assertLess(elapsed.value, 200)

        # timeout = spy.wait(2000)
        # yappi.get_func_stats().print_all()
        # yappi.get_thread_stats().print_all()
示例#20
0
    def test_open_simulator_dialog_and_send_mismatching_message(self):
        stc = self.form.simulator_tab_controller
        assert isinstance(stc, SimulatorTabController)

        self.__setup_project()
        self.add_all_signals_to_simulator()

        stc.simulator_scene.select_all_items()
        stc.simulator_config.project_manager.simulator_timeout_ms = 999999999

        for msg in stc.simulator_scene.get_selected_messages():
            msg.destination = self.dennis
            stc.ui.gvSimulator.message_updated.emit(msg)

        list_model = stc.ui.listViewSimulate.model()
        self.assertEqual(list_model.rowCount(), 2)
        list_model.setData(list_model.createIndex(1, 0),
                           Qt.Checked,
                           role=Qt.CheckStateRole)

        dialog = stc.get_simulator_dialog()

        network_sdr_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(
            network_sdr_name)

        rcv_port = self.get_free_port()
        dialog.simulator.sniffer.rcv_device.set_server_port(rcv_port)

        dialog.simulator.sniffer.adaptive_noise = False
        dialog.simulator.sniffer.automatic_center = False

        dialog.ui.btnStartStop.click()

        while not any("Waiting for message 1" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message 1")
            time.sleep(1)

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        sender = NetworkSDRInterfacePlugin(raw_mode=True, sending=True)
        sender.client_port = rcv_port

        sender.send_raw_data(modulator.modulate("1" * 352), 1)
        time.sleep(0.5)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)

        while not any("Waiting for message 2" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator wait for message 2")
            time.sleep(1)

        sender.send_raw_data(modulator.modulate("10" * 176), 1)
        time.sleep(0.5)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)
        while not any("Mismatch for label:" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for mismatching message")
            time.sleep(1)

        QTest.qWait(250)
        QApplication.processEvents()
        QTest.qWait(100)

        simulator_log = dialog.ui.textEditSimulation.toPlainText()
        self.assertIn("Received message 1", simulator_log)
        self.assertIn("preamble: 11111111", simulator_log)
        self.assertIn("Mismatch for label: preamble", simulator_log)

        dialog.close()
示例#21
0
class VirtualDevice(QObject):
    """
    Wrapper class for providing sending methods for grc and native devices

    """
    started = pyqtSignal()
    stopped = pyqtSignal()
    index_changed = pyqtSignal(int, int)
    sender_needs_restart = pyqtSignal()

    def __init__(self,
                 backend_handler,
                 name: str,
                 mode: Mode,
                 bw,
                 freq,
                 gain,
                 samp_rate,
                 samples_to_send=None,
                 device_ip=None,
                 sending_repeats=1,
                 parent=None,
                 is_ringbuffer=False,
                 raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[
                    name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                self.__dev = ReceiverThread(samp_rate,
                                            freq,
                                            gain,
                                            bw,
                                            parent=parent,
                                            is_ringbuffer=is_ringbuffer)
                self.__dev.index_changed.connect(self.emit_index_changed)
            elif mode == Mode.send:
                self.__dev = SenderThread(samp_rate,
                                          freq,
                                          gain,
                                          bw,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send)
            elif mode == Mode.spectrum:
                self.__dev = SpectrumThread(samp_rate,
                                            freq,
                                            gain,
                                            bw,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.usrp_ip = device_ip
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(
                self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                is_ringbuffer = self.mode == Mode.spectrum or is_ringbuffer

                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(bw,
                                        freq,
                                        gain,
                                        samp_rate,
                                        is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq,
                                        gain,
                                        samp_rate,
                                        device_number=0,
                                        is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq,
                                           gain,
                                           samp_rate,
                                           device_number=0,
                                           is_ringbuffer=is_ringbuffer)
                else:
                    raise NotImplementedError(
                        "Native Backend for {0} not yet implemented".format(
                            name))
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send,
                                                sending_repeats,
                                                skip_device_parameters=True)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(raw_mode=raw_mode)
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

    @property
    def bandwidth(self):
        return self.__dev.bandwidth

    @bandwidth.setter
    def bandwidth(self, value):
        self.__dev.bandwidth = value

    @property
    def bandwidth_is_adjustable(self):
        if self.backend == Backends.grc:
            return True
        elif self.backend == Backends.native:
            return self.__dev.bandwidth_is_adjustable
        elif self.backend == Backends.network:
            return True
        else:
            raise ValueError("Unsupported Backend")

    @property
    def frequency(self):
        if self.backend == Backends.grc:
            return self.__dev.freq
        elif self.backend == Backends.native:
            return self.__dev.frequency
        else:
            raise ValueError("Unsupported Backend")

    @frequency.setter
    def frequency(self, value):
        if self.backend == Backends.grc:
            self.__dev.freq = value
        elif self.backend == Backends.native:
            self.__dev.frequency = value
        elif self.backend == Backends.network:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def gain(self):
        return self.__dev.gain

    @gain.setter
    def gain(self, value):
        self.__dev.gain = value

    @property
    def sample_rate(self):
        return self.__dev.sample_rate

    @sample_rate.setter
    def sample_rate(self, value):
        self.__dev.sample_rate = value

    @property
    def samples_to_send(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.samples_to_send
        else:
            raise ValueError("Unsupported Backend")

    @samples_to_send.setter
    def samples_to_send(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            self.__dev.init_send_parameters(value,
                                            self.num_sending_repeats,
                                            skip_device_parameters=True)
        elif self.backend == Backends.network:
            self.__dev.samples_to_send = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def ip(self):
        if self.backend == Backends.grc:
            return self.__dev.usrp_ip
        elif self.backend == Backends.native:
            return self.__dev.device_ip
        else:
            raise ValueError("Unsupported Backend")

    @ip.setter
    def ip(self, value):
        if self.backend == Backends.grc:
            self.__dev.usrp_ip = value
        elif self.backend == Backends.native:
            self.__dev.device_ip = value
        elif self.backend in (Backends.none, Backends.network):
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def port(self):
        if self.backend in (Backends.grc, Backends.native):
            return self.__dev.port
        else:
            raise ValueError(
                "Port only for gnuradio socket (grc backend) and native backend"
            )

    @port.setter
    def port(self, value):
        if self.backend in (Backends.grc, Backends.native):
            self.__dev.port = value
        else:
            raise ValueError(
                "Port only for gnuradio socket (grc backend) and native backend"
            )

    @property
    def data(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.samples_to_send
            else:
                return self.__dev.receive_buffer
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                raise NotImplementedError("Todo")
            else:
                if self.__dev.raw_mode:
                    return self.__dev.receive_buffer
                else:
                    return self.__dev.received_bits
        else:
            raise ValueError("Unsupported Backend")

    @data.setter
    def data(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.samples_to_send = value
            else:
                self.__dev.receive_buffer = value
        else:
            raise ValueError("Unsupported Backend")

    def free_data(self):
        if self.backend == Backends.grc:
            del self.__dev.data
        elif self.backend == Backends.native:
            del self.__dev.samples_to_send
            del self.__dev.receive_buffer
        elif self.backend == Backends.network:
            self.__dev.free_data()
        elif self.backend == Backends.none:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def num_sending_repeats(self):
        if self.mode == Mode.send:
            if self.backend == Backends.grc:
                return self.__dev.max_repeats
            elif self.backend == Backends.native:
                return self.__dev.sending_repeats
            else:
                raise ValueError("Unsupported Backend")

    @num_sending_repeats.setter
    def num_sending_repeats(self, value):
        if self.mode == Mode.send:
            if self.backend == Backends.grc:
                if value != self.__dev.max_repeats:
                    self.__dev.max_repeats = value
                    self.__dev.current_iteration = 0
            elif self.backend in (Backends.native, Backends.network):
                self.__dev.sending_repeats = value
            else:
                raise ValueError("Unsupported Backend")

    @property
    def current_index(self):
        if self.backend == Backends.grc:
            return self.__dev.current_index
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_recv_index
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_receive_index
        else:
            raise ValueError("Unsupported Backend")

    @current_index.setter
    def current_index(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_index = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_recv_index = value
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_receive_index = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def current_iteration(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.current_sending_repeat
        else:
            raise ValueError("Unsupported Backend")

    @current_iteration.setter
    def current_iteration(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_iteration = value
        elif self.backend in (Backends.native, Backends.network):
            self.__dev.current_sending_repeat = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def sending_finished(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration is None
        elif self.backend == Backends.native:
            return self.__dev.sending_finished
        elif self.backend == Backends.network:
            return self.__dev.current_sent_sample == len(self.samples_to_send)
        else:
            raise ValueError("Unsupported Backend")

    @property
    def spectrum(self):
        if self.mode == Mode.spectrum:
            if self.backend == Backends.grc:
                return self.__dev.x, self.__dev.y
            elif self.backend == Backends.native:
                w = np.abs(np.fft.fft(self.__dev.receive_buffer))
                freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate)
                idx = np.argsort(freqs)
                return freqs[idx].astype(np.float32), w[idx].astype(np.float32)
        else:
            raise ValueError("Spectrum x only available in spectrum mode")

    def start(self):
        if self.backend == Backends.grc:
            self.__dev.setTerminationEnabled(True)
            self.__dev.terminate()
            time.sleep(0.1)
            self.__dev.start(
            )  # Already connected to started signal in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.start_tx_mode(resume=True)
            else:
                self.__dev.start_rx_mode()

            self.emit_started_signal()
        elif self.backend == Backends.network:
            if self.mode == Mode.receive:
                self.__dev.start_tcp_server_for_receiving()
            else:
                self.__dev.start_raw_sending_thread()

            self.emit_started_signal()
        else:
            raise ValueError("Unsupported Backend")

    def stop(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.stop_tx_mode(msg)
            else:
                self.__dev.stop_rx_mode(msg)
            self.emit_stopped_signal()
        elif self.backend == Backends.network:
            self.__dev.stop_tcp_server()
            self.emit_stopped_signal()
        elif self.backend == Backends.none:
            pass
        else:
            logger.error("Stop device: Unsupported backend " +
                         str(self.backend))

    def stop_on_error(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            self.read_errors()  # Clear errors
            self.__dev.stop_rx_mode("Stop on error")
            self.__dev.stop_tx_mode("Stop on error")
            self.emit_stopped_signal()
        else:
            raise ValueError("Unsupported Backend")

    def cleanup(self):
        if self.backend == Backends.grc:
            if self.mode == Mode.send:
                self.__dev.socket.close()
                time.sleep(0.1)
            self.__dev.quit()
            self.data = None

        elif self.backend == Backends.native:
            self.data = None

        elif self.backend == Backends.none:
            pass

        else:
            raise ValueError("Unsupported Backend")

    def emit_stopped_signal(self):
        self.stopped.emit()

    def emit_started_signal(self):
        self.started.emit()

    def emit_sender_needs_restart(self):
        self.sender_needs_restart.emit()

    def emit_index_changed(self, old, new):
        self.index_changed.emit(old, new)

    def read_errors(self):
        if self.backend == Backends.grc:
            return self.__dev.read_errors()
        elif self.backend == Backends.native:
            errors = "\n\n".join(self.__dev.errors)
            self.__dev.errors.clear()
            return errors
        elif self.backend == Backends.network:
            return ""
        else:
            raise ValueError("Unsupported Backend")

    def set_server_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.server_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")

    def set_client_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.client_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")
示例#22
0
class TestSimulator(QtTestCase):
    TIMEOUT = 0.25

    def setUp(self):
        super().setUp()
        settings.OVERWRITE_RECEIVE_BUFFER_SIZE = 50000
        Modulator.FORCE_DTYPE = np.float32

        self.num_zeros_for_pause = 1000

    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        if sys.platform == "win32" and struct.calcsize("P") * 8 == 32:
            print("Skipping test on 32 Bit windows as CI is slow.")
            self.assertTrue(True)
            return

        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(
            len(self.form.simulator_tab_controller.simulator_scene.
                get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog(
        )  # type: SimulatorDialog
        dialog.project_manager.simulator_timeout_ms = 999999999

        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()

        while not any("Waiting for message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(self.TIMEOUT)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages()
                   if msg.source.name == "Alice")
        checksum_label = next(
            lbl for lbl in msg.message_type
            if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 2" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 2")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str), msg=bits)
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 4" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 4")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 6" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 6")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)

        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

    def test_external_program_simulator(self):
        if sys.platform == "win32" and struct.calcsize("P") * 8 == 32:
            print("Skipping test on 32 Bit windows as CI is slow.")
            self.assertTrue(True)
            return

        stc = self.form.simulator_tab_controller  # type: SimulatorTabController
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.project_manager.simulator_timeout_ms = 999999999

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(
            action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        ext_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str
        if sys.platform == "win32":
            ext_program = sys.executable + " " + ext_program

        lbl1.value_type_index = 3
        lbl1.external_program = ext_program
        lbl2.value_type_index = 3
        lbl2.external_program = ext_program

        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.000000001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        file_name = os.path.join(tempfile.gettempdir(), "external_test")
        if os.path.isfile(file_name):
            os.remove(file_name)

        self.assertFalse(os.path.isfile(file_name))
        external_command = "cmd.exe /C copy NUL {}".format(
            file_name) if os.name == "nt" else "touch {}".format(file_name)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)

        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()

        while not any("Waiting for message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(self.TIMEOUT)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42),
                                 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, 2 * self.num_zeros_for_pause), 1)

        while not any("Sending message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message")
            time.sleep(self.TIMEOUT)

        time.sleep(self.TIMEOUT)
        bits = self.__demodulate(conn)
        self.assertEqual(bits[0].rstrip("0"), "101010101")

        while simulator.is_simulating:
            logger.debug("Wait for simulator to finish")
            time.sleep(self.TIMEOUT)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

        self.assertTrue(os.path.isfile(file_name))

    def __demodulate(self, connection: socket.socket):
        connection.settimeout(self.TIMEOUT)
        time.sleep(self.TIMEOUT)

        total_data = []
        while True:
            try:
                data = connection.recv(65536)
                if data:
                    total_data.append(data)
                else:
                    break
            except socket.timeout:
                break

        if len(total_data) == 0:
            logger.error("Did not receive any data from socket.")

        arr = IQArray(
            np.array(np.frombuffer(b"".join(total_data), dtype=np.complex64)))
        signal = Signal("", "")
        signal.iq_array = arr
        pa = ProtocolAnalyzer(signal)
        pa.get_protocol_from_signal()
        return pa.plain_bits_str
示例#23
0
    def __init__(self,
                 backend_handler,
                 name: str,
                 mode: Mode,
                 bw,
                 freq,
                 gain,
                 samp_rate,
                 samples_to_send=None,
                 device_ip=None,
                 sending_repeats=1,
                 parent=None,
                 is_ringbuffer=False,
                 raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[
                    name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                self.__dev = ReceiverThread(samp_rate,
                                            freq,
                                            gain,
                                            bw,
                                            parent=parent,
                                            is_ringbuffer=is_ringbuffer)
                self.__dev.index_changed.connect(self.emit_index_changed)
            elif mode == Mode.send:
                self.__dev = SenderThread(samp_rate,
                                          freq,
                                          gain,
                                          bw,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send)
            elif mode == Mode.spectrum:
                self.__dev = SpectrumThread(samp_rate,
                                            freq,
                                            gain,
                                            bw,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.usrp_ip = device_ip
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(
                self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                is_ringbuffer = self.mode == Mode.spectrum or is_ringbuffer

                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(bw,
                                        freq,
                                        gain,
                                        samp_rate,
                                        is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq,
                                        gain,
                                        samp_rate,
                                        device_number=0,
                                        is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq,
                                           gain,
                                           samp_rate,
                                           device_number=0,
                                           is_ringbuffer=is_ringbuffer)
                else:
                    raise NotImplementedError(
                        "Native Backend for {0} not yet implemented".format(
                            name))
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send,
                                                sending_repeats,
                                                skip_device_parameters=True)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(raw_mode=raw_mode)
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")
示例#24
0
class GeneratorTabController(QWidget):
    def __init__(self,
                 compare_frame_controller: CompareFrameController,
                 project_manager: ProjectManager,
                 parent=None):
        super().__init__(parent)
        self.ui = Ui_GeneratorTab()
        self.ui.setupUi(self)

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = GeneratorTreeModel(compare_frame_controller)
        self.tree_model.set_root_item(
            compare_frame_controller.proto_tree_model.rootItem)
        self.tree_model.controller = self
        self.ui.treeProtocols.setModel(self.tree_model)

        self.has_default_modulation = True

        self.table_model = GeneratorTableModel(
            compare_frame_controller.proto_tree_model.rootItem,
            [Modulator("Modulation")], compare_frame_controller.decodings)
        self.table_model.controller = self
        self.ui.tableMessages.setModel(self.table_model)

        self.label_list_model = GeneratorListModel(None)
        self.ui.listViewProtoLabels.setModel(self.label_list_model)

        self.network_sdr_button_orig_tooltip = self.ui.btnNetworkSDRSend.toolTip(
        )
        self.set_network_sdr_send_button_visibility()
        self.set_rfcat_button_visibility()
        self.network_sdr_plugin = NetworkSDRInterfacePlugin()
        self.rfcat_plugin = RfCatPlugin()
        self.init_rfcat_plugin()

        self.refresh_modulators()
        self.on_selected_modulation_changed()
        self.set_fuzzing_ui_status()
        self.project_manager = project_manager
        self.ui.prBarGeneration.hide()
        self.create_connects(compare_frame_controller)

    @property
    def selected_message_index(self) -> int:
        min_row, _, _, _ = self.ui.tableMessages.selection_range()
        return min_row  #

    @property
    def selected_message(self) -> Message:
        selected_msg_index = self.selected_message_index
        if selected_msg_index == -1 or selected_msg_index >= len(
                self.table_model.protocol.messages):
            return None

        return self.table_model.protocol.messages[selected_msg_index]

    @property
    def active_groups(self):
        return self.tree_model.groups

    @property
    def modulators(self):
        return self.table_model.protocol.modulators

    @property
    def total_modulated_samples(self) -> int:
        return sum(
            int(
                len(msg.encoded_bits) *
                self.modulators[msg.modulator_indx].samples_per_bit +
                msg.pause) for msg in self.table_model.protocol.messages)

    @modulators.setter
    def modulators(self, value):
        assert type(value) == list
        self.table_model.protocol.modulators = value

    def create_connects(self, compare_frame_controller):
        compare_frame_controller.proto_tree_model.modelReset.connect(
            self.refresh_tree)
        compare_frame_controller.participant_changed.connect(
            self.table_model.refresh_vertical_header)
        self.ui.btnEditModulation.clicked.connect(self.show_modulation_dialog)
        self.ui.cBoxModulations.currentIndexChanged.connect(
            self.on_selected_modulation_changed)
        self.ui.tableMessages.selectionModel().selectionChanged.connect(
            self.on_table_selection_changed)
        self.ui.tableMessages.encodings_updated.connect(
            self.on_table_selection_changed)
        self.table_model.undo_stack.indexChanged.connect(
            self.on_undo_stack_index_changed)
        self.table_model.protocol.qt_signals.line_duplicated.connect(
            self.refresh_pause_list)
        self.table_model.protocol.qt_signals.fuzzing_started.connect(
            self.on_fuzzing_started)
        self.table_model.protocol.qt_signals.current_fuzzing_message_changed.connect(
            self.on_current_fuzzing_message_changed)
        self.table_model.protocol.qt_signals.fuzzing_finished.connect(
            self.on_fuzzing_finished)
        self.label_list_model.protolabel_fuzzing_status_changed.connect(
            self.set_fuzzing_ui_status)
        self.ui.cbViewType.currentIndexChanged.connect(
            self.on_view_type_changed)
        self.ui.btnSend.clicked.connect(self.on_btn_send_clicked)
        self.ui.btnSave.clicked.connect(self.on_btn_save_clicked)

        self.project_manager.project_updated.connect(self.on_project_updated)

        self.label_list_model.protolabel_removed.connect(
            self.handle_proto_label_removed)

        self.ui.lWPauses.item_edit_clicked.connect(self.edit_pause_item)
        self.ui.lWPauses.itemSelectionChanged.connect(
            self.on_lWpauses_selection_changed)
        self.ui.lWPauses.lost_focus.connect(self.on_lWPauses_lost_focus)
        self.ui.lWPauses.doubleClicked.connect(self.on_lWPauses_double_clicked)
        self.ui.btnGenerate.clicked.connect(self.generate_file)
        self.label_list_model.protolabel_fuzzing_status_changed.connect(
            self.handle_plabel_fuzzing_state_changed)
        self.ui.btnFuzz.clicked.connect(self.on_btn_fuzzing_clicked)
        self.ui.tableMessages.create_fuzzing_label_clicked.connect(
            self.create_fuzzing_label)
        self.ui.tableMessages.edit_fuzzing_label_clicked.connect(
            self.show_fuzzing_dialog)
        self.ui.listViewProtoLabels.selection_changed.connect(
            self.handle_label_selection_changed)
        self.ui.listViewProtoLabels.edit_on_item_triggered.connect(
            self.show_fuzzing_dialog)

        self.ui.btnNetworkSDRSend.clicked.connect(
            self.on_btn_network_sdr_clicked)
        self.ui.btnRfCatSend.clicked.connect(self.on_btn_rfcat_clicked)

        self.network_sdr_plugin.sending_status_changed.connect(
            self.on_network_sdr_sending_status_changed)
        self.network_sdr_plugin.sending_stop_requested.connect(
            self.on_network_sdr_sending_stop_requested)
        self.network_sdr_plugin.current_send_message_changed.connect(
            self.on_send_message_changed)

    @pyqtSlot()
    def refresh_tree(self):
        self.tree_model.beginResetModel()
        self.tree_model.endResetModel()
        self.ui.treeProtocols.expandAll()

    @pyqtSlot()
    def refresh_table(self):
        self.table_model.update()
        self.ui.tableMessages.resize_columns()
        is_data_there = self.table_model.display_data is not None and len(
            self.table_model.display_data) > 0
        self.ui.btnSend.setEnabled(is_data_there)
        self.ui.btnGenerate.setEnabled(is_data_there)

    @pyqtSlot()
    def refresh_label_list(self):
        self.label_list_model.message = self.selected_message
        self.label_list_model.update()

    @property
    def generator_undo_stack(self) -> QUndoStack:
        return self.table_model.undo_stack

    @pyqtSlot()
    def on_selected_modulation_changed(self):
        cur_ind = self.ui.cBoxModulations.currentIndex()
        min_row, max_row, _, _ = self.ui.tableMessages.selection_range()
        if min_row > -1:
            # Modulation für Selektierte Blöcke setzen
            for row in range(min_row, max_row + 1):
                try:
                    self.table_model.protocol.messages[
                        row].modulator_indx = cur_ind
                except IndexError:
                    continue

        self.show_modulation_info()

    def refresh_modulators(self):
        current_index = 0
        if type(self.sender()) == ModulatorDialogController:
            current_index = self.sender(
            ).ui.comboBoxCustomModulations.currentIndex()
        self.ui.cBoxModulations.clear()
        for modulator in self.modulators:
            self.ui.cBoxModulations.addItem(modulator.name)

        self.ui.cBoxModulations.setCurrentIndex(current_index)

    def show_modulation_info(self):
        show = not self.has_default_modulation or self.modulators[
            0] != Modulator("Modulation")

        if not show:
            self.ui.btnEditModulation.setStyleSheet("background: orange")
            font = QFont()
            font.setBold(True)
            self.ui.btnEditModulation.setFont(font)
        else:
            self.ui.btnEditModulation.setStyleSheet("")
            self.ui.btnEditModulation.setFont(QFont())

        cur_ind = self.ui.cBoxModulations.currentIndex()
        cur_mod = self.modulators[cur_ind]
        self.ui.lCarrierFreqValue.setText(cur_mod.carrier_frequency_str)
        self.ui.lCarrierPhaseValue.setText(cur_mod.carrier_phase_str)
        self.ui.lBitLenValue.setText(cur_mod.bit_len_str)
        self.ui.lSampleRateValue.setText(cur_mod.sample_rate_str)
        mod_type = cur_mod.modulation_type_str
        self.ui.lModTypeValue.setText(mod_type)
        if mod_type == "ASK":
            prefix = "Amplitude"
        elif mod_type == "PSK":
            prefix = "Phase"
        elif mod_type in ("FSK", "GFSK"):
            prefix = "Frequency"
        else:
            prefix = "Unknown Modulation Type (This should not happen...)"

        self.ui.lParamForZero.setText(prefix + " for 0:")
        self.ui.lParamForZeroValue.setText(cur_mod.param_for_zero_str)
        self.ui.lParamForOne.setText(prefix + " for 1:")
        self.ui.lParamForOneValue.setText(cur_mod.param_for_one_str)

    def prepare_modulation_dialog(
            self) -> (ModulatorDialogController, Message):
        preselected_index = self.ui.cBoxModulations.currentIndex()

        min_row, max_row, start, end = self.ui.tableMessages.selection_range()
        if min_row > -1:
            try:
                selected_message = self.table_model.protocol.messages[min_row]
                preselected_index = selected_message.modulator_indx
            except IndexError:
                selected_message = Message([True, False, True, False], 0, [],
                                           MessageType("empty"))
        else:
            selected_message = Message([True, False, True, False], 0, [],
                                       MessageType("empty"))
            if len(self.table_model.protocol.messages) > 0:
                selected_message.bit_len = self.table_model.protocol.messages[
                    0].bit_len

        for m in self.modulators:
            m.default_sample_rate = self.project_manager.device_conf[
                "sample_rate"]

        modulator_dialog = ModulatorDialogController(self.modulators,
                                                     parent=self.parent())
        modulator_dialog.ui.treeViewSignals.setModel(self.tree_model)
        modulator_dialog.ui.treeViewSignals.expandAll()
        modulator_dialog.ui.comboBoxCustomModulations.setCurrentIndex(
            preselected_index)

        modulator_dialog.finished.connect(self.refresh_modulators)
        modulator_dialog.finished.connect(self.refresh_pause_list)

        return modulator_dialog, selected_message

    def initialize_modulation_dialog(self, bits: str,
                                     dialog: ModulatorDialogController):
        dialog.on_modulation_type_changed(
        )  # for drawing modulated signal initially
        dialog.original_bits = bits
        dialog.ui.linEdDataBits.setText(bits)
        dialog.ui.gVOriginalSignal.signal_tree_root = self.tree_model.rootItem
        dialog.draw_original_signal()
        dialog.ui.gVModulated.show_full_scene(reinitialize=True)
        dialog.ui.gVData.show_full_scene(reinitialize=True)
        dialog.ui.gVData.auto_fit_view()
        dialog.ui.gVCarrier.show_full_scene(reinitialize=True)
        dialog.ui.gVCarrier.auto_fit_view()

    def init_rfcat_plugin(self):
        self.set_rfcat_button_visibility()
        self.rfcat_plugin = RfCatPlugin()
        self.rfcat_plugin.current_send_message_changed.connect(
            self.on_send_message_changed)
        self.ui.btnRfCatSend.setEnabled(self.rfcat_plugin.rfcat_is_found)

    @pyqtSlot()
    def on_undo_stack_index_changed(self):
        self.refresh_table()
        self.refresh_pause_list()
        self.refresh_label_list()
        self.refresh_estimated_time()
        self.set_fuzzing_ui_status()

    @pyqtSlot()
    def show_modulation_dialog(self):
        modulator_dialog, message = self.prepare_modulation_dialog()
        modulator_dialog.showMaximized()

        self.initialize_modulation_dialog(message.encoded_bits_str[0:10],
                                          modulator_dialog)
        self.has_default_modulation = False

    @pyqtSlot()
    def on_table_selection_changed(self):
        min_row, max_row, start, end = self.ui.tableMessages.selection_range()

        if min_row == -1:
            self.ui.lEncodingValue.setText("-")  #
            self.ui.lEncodingValue.setToolTip("")
            self.label_list_model.message = None
            return

        container = self.table_model.protocol
        message = container.messages[min_row]
        self.label_list_model.message = message
        decoder_name = message.decoder.name
        metrics = QFontMetrics(self.ui.lEncodingValue.font())
        elidedName = metrics.elidedText(decoder_name, Qt.ElideRight,
                                        self.ui.lEncodingValue.width())
        self.ui.lEncodingValue.setText(elidedName)
        self.ui.lEncodingValue.setToolTip(decoder_name)
        self.ui.cBoxModulations.blockSignals(True)
        self.ui.cBoxModulations.setCurrentIndex(message.modulator_indx)
        self.show_modulation_info()
        self.ui.cBoxModulations.blockSignals(False)

    @pyqtSlot(int)
    def edit_pause_item(self, index: int):
        message = self.table_model.protocol.messages[index]
        cur_len = message.pause
        new_len, ok = QInputDialog.getInt(self,
                                          self.tr("Enter new Pause Length"),
                                          self.tr("Pause Length:"), cur_len, 0)
        if ok:
            message.pause = new_len
            self.refresh_pause_list()

    @pyqtSlot()
    def on_lWPauses_double_clicked(self):
        sel_indexes = [
            index.row() for index in self.ui.lWPauses.selectedIndexes()
        ]
        if len(sel_indexes) > 0:
            self.edit_pause_item(sel_indexes[0])

    @pyqtSlot()
    def refresh_pause_list(self):
        self.ui.lWPauses.clear()
        fmt_str = "Pause ({1:d}-{2:d}) <{0:d} samples ({3})>"
        for i, pause in enumerate(self.table_model.protocol.pauses):
            sr = self.modulators[self.table_model.protocol.messages[i].
                                 modulator_indx].sample_rate
            item = fmt_str.format(pause, i + 1, i + 2,
                                  Formatter.science_time(pause / sr))
            self.ui.lWPauses.addItem(item)

    @pyqtSlot()
    def on_lWpauses_selection_changed(self):
        rows = [index.row() for index in self.ui.lWPauses.selectedIndexes()]
        if len(rows) == 0:
            return
        self.ui.tableMessages.show_pause_active = True
        self.ui.tableMessages.pause_row = rows[0]
        self.ui.tableMessages.viewport().update()
        self.ui.tableMessages.scrollTo(self.table_model.index(rows[0], 0))

    @pyqtSlot()
    def on_lWPauses_lost_focus(self):
        self.ui.tableMessages.show_pause_active = False
        self.ui.tableMessages.viewport().update()

    @pyqtSlot()
    def generate_file(self):
        try:
            total_samples = self.total_modulated_samples
            buffer = self.prepare_modulation_buffer(total_samples,
                                                    show_error=False)
            if buffer is None:
                Errors.generic_error(
                    self.tr("File too big"),
                    self.tr("This file would get too big to save."))
                self.unsetCursor()
                return
            modulated_samples = self.modulate_data(buffer)
            FileOperator.save_data_dialog("", modulated_samples, parent=self)
        except Exception as e:
            Errors.generic_error(self.tr("Failed to generate data"), str(e),
                                 traceback.format_exc())
            self.unsetCursor()

    def prepare_modulation_buffer(self,
                                  total_samples: int,
                                  show_error=True) -> np.ndarray:
        memory_size_for_buffer = total_samples * 8
        logger.debug("Allocating {0:.2f}MB for modulated samples".format(
            memory_size_for_buffer / (1024**2)))
        try:
            return np.zeros(total_samples, dtype=np.complex64)
        except MemoryError:
            if show_error:
                Errors.not_enough_ram_for_sending_precache(
                    memory_size_for_buffer)
            return None

    def modulate_data(self, buffer: np.ndarray) -> np.ndarray:
        """
        
        :param buffer: Buffer in which the modulated data shall be written, initialized with zeros
        :return: 
        """
        self.ui.prBarGeneration.show()
        self.ui.prBarGeneration.setValue(0)
        self.ui.prBarGeneration.setMaximum(self.table_model.row_count)

        pos = 0
        for i in range(0, self.table_model.row_count):
            message = self.table_model.protocol.messages[i]
            modulator = self.modulators[message.modulator_indx]
            # We do not need to modulate the pause extra, as result is already initialized with zeros
            modulator.modulate(start=pos, data=message.encoded_bits, pause=0)
            buffer[pos:pos + len(modulator.modulated_samples
                                 )] = modulator.modulated_samples
            pos += len(modulator.modulated_samples) + message.pause
            self.ui.prBarGeneration.setValue(i + 1)
            QApplication.instance().processEvents()

        self.ui.prBarGeneration.hide()
        return buffer

    @pyqtSlot(int)
    def show_fuzzing_dialog(self, label_index: int):
        view = self.ui.cbViewType.currentIndex()

        if self.label_list_model.message is not None:
            msg_index = self.table_model.protocol.messages.index(
                self.label_list_model.message)
            fdc = FuzzingDialogController(protocol=self.table_model.protocol,
                                          label_index=label_index,
                                          msg_index=msg_index,
                                          proto_view=view,
                                          parent=self)
            fdc.show()
            fdc.finished.connect(self.refresh_label_list)
            fdc.finished.connect(self.refresh_table)
            fdc.finished.connect(self.set_fuzzing_ui_status)

    @pyqtSlot()
    def handle_plabel_fuzzing_state_changed(self):
        self.refresh_table()
        self.label_list_model.update()

    @pyqtSlot(ProtocolLabel)
    def handle_proto_label_removed(self, plabel: ProtocolLabel):
        self.refresh_label_list()
        self.refresh_table()
        self.set_fuzzing_ui_status()

    @pyqtSlot()
    def on_btn_fuzzing_clicked(self):
        fuz_mode = "Successive"
        if self.ui.rbConcurrent.isChecked():
            fuz_mode = "Concurrent"
        elif self.ui.rBExhaustive.isChecked():
            fuz_mode = "Exhaustive"

        self.setCursor(Qt.WaitCursor)
        fuzz_action = Fuzz(self.table_model.protocol, fuz_mode)
        self.table_model.undo_stack.push(fuzz_action)
        self.unsetCursor()

    @pyqtSlot()
    def set_fuzzing_ui_status(self):
        btn_was_enabled = self.ui.btnFuzz.isEnabled()
        fuzz_active = any(lbl.active_fuzzing
                          for msg in self.table_model.protocol.messages
                          for lbl in msg.message_type)
        self.ui.btnFuzz.setEnabled(fuzz_active)
        if self.ui.btnFuzz.isEnabled() and not btn_was_enabled:
            font = self.ui.btnFuzz.font()
            font.setBold(True)
            self.ui.btnFuzz.setFont(font)
        else:
            font = self.ui.btnFuzz.font()
            font.setBold(False)
            self.ui.btnFuzz.setFont(font)
            self.ui.btnFuzz.setStyleSheet("")

        has_same_message = self.table_model.protocol.multiple_fuzz_labels_per_message
        self.ui.rBSuccessive.setEnabled(has_same_message)
        self.ui.rBExhaustive.setEnabled(has_same_message)
        self.ui.rbConcurrent.setEnabled(has_same_message)

    def refresh_existing_encodings(self, encodings_from_file):
        """
        Refresh existing encodings for messages, when encoding was changed by user in dialog

        :return:
        """
        update = False

        for msg in self.table_model.protocol.messages:
            i = next((i for i, d in enumerate(encodings_from_file)
                      if d.name == msg.decoder.name), 0)
            if msg.decoder != encodings_from_file[i]:
                update = True
                msg.decoder = encodings_from_file[i]
                msg.clear_decoded_bits()
                msg.clear_encoded_bits()

        if update:
            self.refresh_table()
            self.refresh_estimated_time()

    @pyqtSlot()
    def refresh_estimated_time(self):
        c = self.table_model.protocol
        if c.num_messages == 0:
            self.ui.lEstimatedTime.setText("Estimated Time: ")
            return

        avg_msg_len = numpy.mean([len(msg.encoded_bits) for msg in c.messages])
        avg_bit_len = numpy.mean([m.samples_per_bit for m in self.modulators])
        avg_sample_rate = numpy.mean([m.sample_rate for m in self.modulators])
        pause_samples = sum(c.pauses)
        nsamples = c.num_messages * avg_msg_len * avg_bit_len + pause_samples

        self.ui.lEstimatedTime.setText(
            locale.format_string("Estimated Time: %.04f seconds",
                                 nsamples / avg_sample_rate))

    @pyqtSlot(int, int, int)
    def create_fuzzing_label(self, msg_index: int, start: int, end: int):
        con = self.table_model.protocol
        start, end = con.convert_range(start, end - 1,
                                       self.ui.cbViewType.currentIndex(), 0,
                                       False, msg_index)
        lbl = con.create_fuzzing_label(start, end, msg_index)
        self.show_fuzzing_dialog(con.protocol_labels.index(lbl))

    @pyqtSlot()
    def handle_label_selection_changed(self):
        rows = [
            index.row()
            for index in self.ui.listViewProtoLabels.selectedIndexes()
        ]
        if len(rows) == 0:
            return

        maxrow = numpy.max(rows)

        try:
            label = self.table_model.protocol.protocol_labels[maxrow]
        except IndexError:
            return
        if label.show and self.selected_message:
            start, end = self.selected_message.get_label_range(
                lbl=label, view=self.table_model.proto_view, decode=False)
            indx = self.table_model.index(0, int((start + end) / 2))
            self.ui.tableMessages.scrollTo(indx)

    @pyqtSlot()
    def on_view_type_changed(self):
        self.setCursor(Qt.WaitCursor)
        self.table_model.proto_view = self.ui.cbViewType.currentIndex()
        self.ui.tableMessages.resize_columns()
        self.unsetCursor()

    @pyqtSlot()
    def on_btn_send_clicked(self):
        try:
            total_samples = self.total_modulated_samples
            buffer = self.prepare_modulation_buffer(total_samples)
            if buffer is not None:
                modulated_data = self.modulate_data(buffer)
            else:
                # Enter continuous mode
                modulated_data = None

            try:
                if modulated_data is not None:
                    try:
                        dialog = SendDialogController(
                            self.project_manager,
                            modulated_data=modulated_data,
                            parent=self)
                    except MemoryError:
                        # Not enough memory for device buffer so we need to create a continuous send dialog
                        del modulated_data
                        Errors.not_enough_ram_for_sending_precache(None)
                        dialog = ContinuousSendDialogController(
                            self.project_manager,
                            self.table_model.protocol.messages,
                            self.modulators,
                            total_samples,
                            parent=self)
                else:
                    dialog = ContinuousSendDialogController(
                        self.project_manager,
                        self.table_model.protocol.messages,
                        self.modulators,
                        total_samples,
                        parent=self)
            except OSError as e:
                logger.error(repr(e))
                return
            if dialog.has_empty_device_list:
                Errors.no_device()
                dialog.close()
                return

            dialog.recording_parameters.connect(
                self.project_manager.set_recording_parameters)
            dialog.show()
            dialog.graphics_view.show_full_scene(reinitialize=True)
        except Exception as e:
            Errors.generic_error(self.tr("Failed to generate data"), str(e),
                                 traceback.format_exc())
            self.unsetCursor()

    @pyqtSlot()
    def on_btn_save_clicked(self):
        filename = FileOperator.get_save_file_name("profile.fuzz",
                                                   caption="Save fuzz profile")
        if filename:
            self.table_model.protocol.to_xml_file(filename)

    def load_from_file(self, filename: str):
        try:
            self.table_model.protocol.from_xml_file(filename)
            self.refresh_pause_list()
            self.refresh_estimated_time()
            self.refresh_modulators()
            self.show_modulation_info()
            self.refresh_table()
            self.set_fuzzing_ui_status()
        except:
            logger.error(
                "You done something wrong to the xml fuzzing profile.")

    @pyqtSlot()
    def on_project_updated(self):
        self.table_model.participants = self.project_manager.participants
        self.table_model.refresh_vertical_header()

    def set_network_sdr_send_button_visibility(self):
        is_plugin_enabled = PluginManager().is_plugin_enabled(
            "NetworkSDRInterface")
        self.ui.btnNetworkSDRSend.setVisible(is_plugin_enabled)

    def set_rfcat_button_visibility(self):
        is_plugin_enabled = PluginManager().is_plugin_enabled("RfCat")
        self.ui.btnRfCatSend.setVisible(is_plugin_enabled)

    @pyqtSlot()
    def on_btn_network_sdr_clicked(self):
        if not self.network_sdr_plugin.is_sending:
            messages = self.table_model.protocol.messages
            sample_rates = [
                self.modulators[msg.modulator_indx].sample_rate
                for msg in messages
            ]
            self.network_sdr_plugin.start_message_sending_thread(
                messages, sample_rates)
        else:
            self.network_sdr_plugin.stop_sending_thread()

    @pyqtSlot(bool)
    def on_network_sdr_sending_status_changed(self, is_sending: bool):
        self.ui.btnNetworkSDRSend.setChecked(is_sending)
        self.ui.btnNetworkSDRSend.setEnabled(True)
        self.ui.btnNetworkSDRSend.setToolTip(
            "Sending in progress" if is_sending else self.
            network_sdr_button_orig_tooltip)
        if not is_sending:
            self.ui.tableMessages.clearSelection()

    @pyqtSlot()
    def on_network_sdr_sending_stop_requested(self):
        self.ui.btnNetworkSDRSend.setToolTip("Stopping sending")
        self.ui.btnNetworkSDRSend.setEnabled(False)

    @pyqtSlot(int)
    def on_send_message_changed(self, message_index: int):
        self.ui.tableMessages.selectRow(message_index)

    @pyqtSlot()
    def on_btn_rfcat_clicked(self):
        if not self.rfcat_plugin.is_sending:
            messages = self.table_model.protocol.messages
            sample_rates = [
                self.modulators[msg.modulator_indx].sample_rate
                for msg in messages
            ]
            self.rfcat_plugin.start_message_sending_thread(
                messages, sample_rates, self.modulators, self.project_manager)
        else:
            self.rfcat_plugin.stop_sending_thread()

    @pyqtSlot(int)
    def on_fuzzing_started(self, num_values: int):
        self.ui.stackedWidgetFuzzing.setCurrentWidget(
            self.ui.pageFuzzingProgressBar)
        self.ui.progressBarFuzzing.setMaximum(num_values)
        self.ui.progressBarFuzzing.setValue(0)
        QApplication.instance().processEvents()

    @pyqtSlot()
    def on_fuzzing_finished(self):
        self.ui.stackedWidgetFuzzing.setCurrentWidget(self.ui.pageFuzzingUI)

    @pyqtSlot(int)
    def on_current_fuzzing_message_changed(self, current_message: int):
        self.ui.progressBarFuzzing.setValue(current_message)
        QApplication.instance().processEvents()
示例#25
0
class VirtualDevice(QObject):
    """
    Wrapper class for providing sending methods for grc and native devices

    """
    started = pyqtSignal()
    stopped = pyqtSignal()
    sender_needs_restart = pyqtSignal()

    fatal_error_occurred = pyqtSignal(str)
    ready_for_action = pyqtSignal()

    data_received = pyqtSignal(np.ndarray)  # for direct demodulation in sniffer

    continuous_send_msg = "Continuous send mode is not supported for GNU Radio backend. " \
                          "You can change the configured device backend in options."

    def __init__(self, backend_handler, name: str, mode: Mode, freq=None, sample_rate=None, bandwidth=None,
                 gain=None, if_gain=None, baseband_gain=None, samples_to_send=None,
                 device_ip=None, sending_repeats=1, parent=None, resume_on_full_receive_buffer=False, raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        resume_on_full_receive_buffer = self.mode == Mode.spectrum or resume_on_full_receive_buffer

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent, resume_on_full_receive_buffer=resume_on_full_receive_buffer)
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send) if samples_to_send is not None else 2 ** 15
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq, gain, sample_rate, device_number=0,
                                        resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq, gain, sample_rate, bandwidth, device_number=0,
                                           resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name == "limesdr":
                    from urh.dev.native.LimeSDR import LimeSDR
                    self.__dev = LimeSDR(freq, gain, sample_rate, bandwidth, gain,
                                         resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("airspy"):
                    from urh.dev.native.AirSpy import AirSpy
                    self.__dev = AirSpy(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                        resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("usrp"):
                    from urh.dev.native.USRP import USRP
                    self.__dev = USRP(freq, gain, sample_rate, bandwidth, gain,
                                      resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("sdrplay"):
                    from urh.dev.native.SDRPlay import SDRPlay
                    self.__dev = SDRPlay(freq, gain, bandwidth, gain, if_gain=if_gain,
                                         resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name == "soundcard":
                    from urh.dev.native.SoundCard import SoundCard
                    self.__dev = SoundCard(sample_rate, resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                else:
                    raise NotImplementedError("Native Backend for {0} not yet implemented".format(name))

            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                    resume_on_full_receive_buffer)
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send, sending_repeats)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(raw_mode=raw_mode,
                                                   resume_on_full_receive_buffer=resume_on_full_receive_buffer,
                                                   spectrum=self.mode == Mode.spectrum, sending=self.mode == Mode.send)
            self.__dev.send_connection_established.connect(self.emit_ready_for_action)
            self.__dev.receive_server_started.connect(self.emit_ready_for_action)
            self.__dev.error_occurred.connect(self.emit_fatal_error_occurred)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

        if hasattr(self.__dev, "data_received"):
            self.__dev.data_received.connect(self.data_received.emit)

        if mode == Mode.spectrum:
            self.__dev.is_in_spectrum_mode = True

    @property
    def has_multi_device_support(self):
        return hasattr(self.__dev, "has_multi_device_support") and self.__dev.has_multi_device_support

    @property
    def device_serial(self):
        if hasattr(self.__dev, "device_serial"):
            return self.__dev.device_serial
        else:
            return None

    @device_serial.setter
    def device_serial(self, value):
        if hasattr(self.__dev, "device_serial"):
            self.__dev.device_serial = value

    @property
    def device_number(self):
        if hasattr(self.__dev, "device_number"):
            return self.__dev.device_number
        else:
            return None

    @device_number.setter
    def device_number(self, value):
        if hasattr(self.__dev, "device_number"):
            self.__dev.device_number = value

    @property
    def bandwidth(self):
        return self.__dev.bandwidth

    @bandwidth.setter
    def bandwidth(self, value):
        self.__dev.bandwidth = value

    @property
    def bandwidth_is_adjustable(self):
        if self.backend == Backends.grc:
            return True
        elif self.backend == Backends.native:
            return self.__dev.bandwidth_is_adjustable
        elif self.backend == Backends.network:
            return True
        else:
            raise ValueError("Unsupported Backend")

    @property
    def frequency(self):
        if self.backend == Backends.grc:
            return self.__dev.freq
        elif self.backend == Backends.native:
            return self.__dev.frequency
        else:
            raise ValueError("Unsupported Backend")

    @frequency.setter
    def frequency(self, value):
        if self.backend == Backends.grc:
            self.__dev.freq = value
        elif self.backend == Backends.native:
            self.__dev.frequency = value
        elif self.backend == Backends.network:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def num_samples_to_send(self) -> int:
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.num_samples_to_send
        else:
            raise ValueError(self.continuous_send_msg)

    @num_samples_to_send.setter
    def num_samples_to_send(self, value: int):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.num_samples_to_send = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_send_continuous(self) -> bool:
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.sending_is_continuous
        else:
            raise ValueError(self.continuous_send_msg)

    @is_send_continuous.setter
    def is_send_continuous(self, value: bool):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.sending_is_continuous = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_raw_mode(self) -> bool:
        if self.backend == Backends.network:
            return self.__dev.raw_mode
        else:
            return True

    @property
    def continuous_send_ring_buffer(self):
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.continuous_send_ring_buffer
        else:
            raise ValueError(self.continuous_send_msg)

    @continuous_send_ring_buffer.setter
    def continuous_send_ring_buffer(self, value):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.continuous_send_ring_buffer = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_in_spectrum_mode(self):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            return self.__dev.is_in_spectrum_mode
        else:
            raise ValueError("Unsupported Backend")

    @is_in_spectrum_mode.setter
    def is_in_spectrum_mode(self, value: bool):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            self.__dev.is_in_spectrum_mode = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def gain(self):
        return self.__dev.gain

    @gain.setter
    def gain(self, value):
        try:
            self.__dev.gain = value
        except AttributeError as e:
            logger.warning(str(e))

    @property
    def if_gain(self):
        try:
            return self.__dev.if_gain
        except AttributeError as e:
            logger.warning(str(e))

    @if_gain.setter
    def if_gain(self, value):
        try:
            self.__dev.if_gain = value
        except AttributeError as e:
            logger.warning(str(e))

    @property
    def baseband_gain(self):
        return self.__dev.baseband_gain

    @baseband_gain.setter
    def baseband_gain(self, value):
        self.__dev.baseband_gain = value

    @property
    def sample_rate(self):
        return self.__dev.sample_rate

    @sample_rate.setter
    def sample_rate(self, value):
        self.__dev.sample_rate = value

    @property
    def channel_index(self) -> int:
        return self.__dev.channel_index

    @channel_index.setter
    def channel_index(self, value: int):
        self.__dev.channel_index = value

    @property
    def antenna_index(self) -> int:
        return self.__dev.antenna_index

    @antenna_index.setter
    def antenna_index(self, value: int):
        self.__dev.antenna_index = value

    @property
    def freq_correction(self):
        return self.__dev.freq_correction

    @freq_correction.setter
    def freq_correction(self, value):
        self.__dev.freq_correction = value

    @property
    def direct_sampling_mode(self) -> int:
        return self.__dev.direct_sampling_mode

    @direct_sampling_mode.setter
    def direct_sampling_mode(self, value):
        self.__dev.direct_sampling_mode = value

    @property
    def emit_data_received_signal(self):
        return self.__dev.emit_data_received_signal

    @emit_data_received_signal.setter
    def emit_data_received_signal(self, value):
        self.__dev.emit_data_received_signal = value

    @property
    def samples_to_send(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.samples_to_send
        else:
            raise ValueError("Unsupported Backend")

    @samples_to_send.setter
    def samples_to_send(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            self.__dev.init_send_parameters(value, self.num_sending_repeats)
        elif self.backend == Backends.network:
            self.__dev.samples_to_send = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def ip(self):
        if self.backend == Backends.grc:
            return self.__dev.device_ip
        elif self.backend == Backends.native:
            return self.__dev.device_ip
        else:
            raise ValueError("Unsupported Backend")

    @ip.setter
    def ip(self, value):
        if self.backend == Backends.grc:
            self.__dev.device_ip = value
        elif self.backend == Backends.native:
            self.__dev.device_ip = value
        elif self.backend in (Backends.none, Backends.network):
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def port(self):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            return self.__dev.port
        else:
            raise ValueError("Unsupported Backend")

    @port.setter
    def port(self, value):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            self.__dev.port = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def data(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.samples_to_send
            else:
                return self.__dev.receive_buffer
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                raise NotImplementedError("Todo")
            else:
                if self.__dev.raw_mode:
                    return self.__dev.receive_buffer
                else:
                    return self.__dev.received_bits
        else:
            raise ValueError("Unsupported Backend")

    @data.setter
    def data(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.samples_to_send = value
            else:
                self.__dev.receive_buffer = value
        else:
            logger.warning("{}:{} has no data".format(self.__class__.__name__, self.backend.name))

    def free_data(self):
        if self.backend == Backends.grc:
            self.__dev.data = None
        elif self.backend == Backends.native:
            self.__dev.samples_to_send = None
            self.__dev.receive_buffer = None
        elif self.backend == Backends.network:
            self.__dev.free_data()
        elif self.backend == Backends.none:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def resume_on_full_receive_buffer(self) -> bool:
        return self.__dev.resume_on_full_receive_buffer

    @resume_on_full_receive_buffer.setter
    def resume_on_full_receive_buffer(self, value: bool):
        if value != self.__dev.resume_on_full_receive_buffer:
            self.__dev.resume_on_full_receive_buffer = value
            if self.backend == Backends.native:
                self.__dev.receive_buffer = None
            elif self.backend == Backends.grc:
                self.__dev.data = None

    @property
    def num_sending_repeats(self):
        return self.__dev.sending_repeats

    @num_sending_repeats.setter
    def num_sending_repeats(self, value):
        self.__dev.sending_repeats = value

    @property
    def current_index(self):
        if self.backend == Backends.grc:
            return self.__dev.current_index
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_recv_index
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_receive_index
        else:
            raise ValueError("Unsupported Backend")

    @current_index.setter
    def current_index(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_index = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_recv_index = value
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_receive_index = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def current_iteration(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.current_sending_repeat
        else:
            raise ValueError("Unsupported Backend")

    @current_iteration.setter
    def current_iteration(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_iteration = value
        elif self.backend in (Backends.native, Backends.network):
            self.__dev.current_sending_repeat = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def sending_finished(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration is None
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.sending_finished
        else:
            raise ValueError("Unsupported Backend")

    @property
    def spectrum(self):
        if self.mode == Mode.spectrum:
            if self.backend == Backends.grc:
                return self.__dev.x, self.__dev.y
            elif self.backend == Backends.native or self.backend == Backends.network:
                w = np.abs(np.fft.fft(self.__dev.receive_buffer))
                freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate)
                idx = np.argsort(freqs)
                return freqs[idx].astype(np.float32), w[idx].astype(np.float32)
        else:
            raise ValueError("Spectrum x only available in spectrum mode")

    def start(self):
        if self.backend == Backends.grc:
            self.__dev.setTerminationEnabled(True)
            self.__dev.terminate()
            time.sleep(0.1)
            self.__dev.start()  # Already connected to started signal in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.start_tx_mode(resume=True)
            else:
                self.__dev.start_rx_mode()

            self.emit_started_signal()
        elif self.backend == Backends.network:
            if self.mode == Mode.receive or self.mode == Mode.spectrum:
                self.__dev.start_tcp_server_for_receiving()
            else:
                self.__dev.start_raw_sending_thread()

            self.emit_started_signal()
        else:
            raise ValueError("Unsupported Backend")

    def stop(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.stop_tx_mode(msg)
            else:
                self.__dev.stop_rx_mode(msg)
            self.emit_stopped_signal()
        elif self.backend == Backends.network:
            self.__dev.stop_tcp_server()
            self.__dev.stop_sending_thread()
            self.emit_stopped_signal()
        elif self.backend == Backends.none:
            pass
        else:
            logger.error("Stop device: Unsupported backend " + str(self.backend))

    def stop_on_error(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            self.read_messages()  # Clear errors
            self.__dev.stop_rx_mode("Stop on error")
            self.__dev.stop_tx_mode("Stop on error")
            self.emit_stopped_signal()
        else:
            raise ValueError("Unsupported Backend")

    def cleanup(self):
        if self.backend == Backends.grc:
            if self.mode == Mode.send:
                self.__dev.socket.close()
                time.sleep(0.1)
            self.__dev.quit()
            self.data = None

        elif self.backend == Backends.native:
            self.data = None

        elif self.backend == Backends.none:
            pass

        else:
            raise ValueError("Unsupported Backend")

    def emit_stopped_signal(self):
        self.stopped.emit()

    def emit_started_signal(self):
        self.started.emit()

    def emit_sender_needs_restart(self):
        self.sender_needs_restart.emit()

    def read_messages(self) -> str:
        """
        returns a string of new device messages separated by newlines

        :return:
        """
        if self.backend == Backends.grc:
            errors = self.__dev.read_errors()

            if "FATAL: " in errors:
                self.fatal_error_occurred.emit(errors[errors.index("FATAL: "):])

            return errors
        elif self.backend == Backends.native:
            messages = "\n".join(self.__dev.device_messages)
            self.__dev.device_messages.clear()

            if messages and not messages.endswith("\n"):
                messages += "\n"

            if "successfully started" in messages:
                self.ready_for_action.emit()
            elif "failed to start" in messages:
                self.fatal_error_occurred.emit(messages[messages.index("failed to start"):])

            return messages
        elif self.backend == Backends.network:
            return ""
        else:
            raise ValueError("Unsupported Backend")

    def set_server_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.server_port = port
        else:
            raise ValueError("Setting port only supported for NetworkSDR Plugin")

    def set_client_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.client_port = port
        else:
            raise ValueError("Setting port only supported for NetworkSDR Plugin")

    def get_device_list(self):
        if hasattr(self.__dev, "get_device_list"):
            return self.__dev.get_device_list()
        else:
            return []

    def increase_gr_port(self):
        if self.backend == Backends.grc:
            self.__dev.gr_port += 1
            logger.info("Retry with port " + str(self.__dev.gr_port))
        else:
            raise ValueError("Only for GR backend")

    def emit_ready_for_action(self):
        """
        Notify observers that device is successfully initialized
        :return:
        """
        self.ready_for_action.emit()

    def emit_fatal_error_occurred(self, msg: str):
        self.fatal_error_occurred.emit(msg)
示例#26
0
class VirtualDevice(QObject):
    """
    Wrapper class for providing sending methods for grc and native devices

    """
    started = pyqtSignal()
    stopped = pyqtSignal()
    index_changed = pyqtSignal(int, int)
    sender_needs_restart = pyqtSignal()

    def __init__(self,
                 backend_handler,
                 name: str,
                 mode: Mode,
                 freq=None,
                 sample_rate=None,
                 bandwidth=None,
                 gain=None,
                 if_gain=None,
                 baseband_gain=None,
                 samples_to_send=None,
                 device_ip=None,
                 sending_repeats=1,
                 parent=None,
                 is_ringbuffer=False,
                 raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[
                    name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(freq,
                                            sample_rate,
                                            bandwidth,
                                            gain,
                                            if_gain,
                                            baseband_gain,
                                            parent=parent,
                                            is_ringbuffer=is_ringbuffer)
                self.__dev.index_changed.connect(self.emit_index_changed)
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq,
                                          sample_rate,
                                          bandwidth,
                                          gain,
                                          if_gain,
                                          baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send)
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq,
                                            sample_rate,
                                            bandwidth,
                                            gain,
                                            if_gain,
                                            baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(
                self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                is_ringbuffer = self.mode == Mode.spectrum or is_ringbuffer

                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain,
                                        if_gain, baseband_gain, is_ringbuffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq,
                                        gain,
                                        sample_rate,
                                        device_number=0,
                                        is_ringbuffer=is_ringbuffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq,
                                           gain,
                                           sample_rate,
                                           bandwidth,
                                           device_number=0,
                                           is_ringbuffer=is_ringbuffer)
                elif name == "limesdr":
                    from urh.dev.native.LimeSDR import LimeSDR
                    self.__dev = LimeSDR(freq,
                                         gain,
                                         sample_rate,
                                         bandwidth,
                                         gain,
                                         is_ringbuffer=is_ringbuffer)
                elif name.startswith("airspy"):
                    from urh.dev.native.AirSpy import AirSpy
                    self.__dev = AirSpy(freq,
                                        sample_rate,
                                        bandwidth,
                                        gain,
                                        if_gain,
                                        baseband_gain,
                                        is_ringbuffer=is_ringbuffer)
                else:
                    raise NotImplementedError(
                        "Native Backend for {0} not yet implemented".format(
                            name))

            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain,
                                    if_gain, baseband_gain, is_ringbuffer)
                self.__dev.BYTES_PER_SAMPLE = 4
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send,
                                                sending_repeats)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(
                raw_mode=raw_mode, spectrum=self.mode == Mode.spectrum)
            self.__dev.rcv_index_changed.connect(self.emit_index_changed)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

    @property
    def bandwidth(self):
        return self.__dev.bandwidth

    @bandwidth.setter
    def bandwidth(self, value):
        self.__dev.bandwidth = value

    @property
    def bandwidth_is_adjustable(self):
        if self.backend == Backends.grc:
            return True
        elif self.backend == Backends.native:
            return self.__dev.bandwidth_is_adjustable
        elif self.backend == Backends.network:
            return True
        else:
            raise ValueError("Unsupported Backend")

    @property
    def frequency(self):
        if self.backend == Backends.grc:
            return self.__dev.freq
        elif self.backend == Backends.native:
            return self.__dev.frequency
        else:
            raise ValueError("Unsupported Backend")

    @frequency.setter
    def frequency(self, value):
        if self.backend == Backends.grc:
            self.__dev.freq = value
        elif self.backend == Backends.native:
            self.__dev.frequency = value
        elif self.backend == Backends.network:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def gain(self):
        return self.__dev.gain

    @gain.setter
    def gain(self, value):
        self.__dev.gain = value

    @property
    def if_gain(self):
        return self.__dev.if_gain

    @if_gain.setter
    def if_gain(self, value):
        self.__dev.if_gain = value

    @property
    def baseband_gain(self):
        return self.__dev.baseband_gain

    @baseband_gain.setter
    def baseband_gain(self, value):
        self.__dev.baseband_gain = value

    @property
    def sample_rate(self):
        return self.__dev.sample_rate

    @sample_rate.setter
    def sample_rate(self, value):
        self.__dev.sample_rate = value

    @property
    def channel_index(self) -> int:
        return self.__dev.channel_index

    @channel_index.setter
    def channel_index(self, value: int):
        self.__dev.channel_index = value

    @property
    def antenna_index(self) -> int:
        return self.__dev.antenna_index

    @antenna_index.setter
    def antenna_index(self, value: int):
        self.__dev.antenna_index = value

    @property
    def freq_correction(self):
        return self.__dev.freq_correction

    @freq_correction.setter
    def freq_correction(self, value):
        self.__dev.freq_correction = value

    @property
    def direct_sampling_mode(self) -> int:
        return self.__dev.direct_sampling_mode

    @direct_sampling_mode.setter
    def direct_sampling_mode(self, value):
        self.__dev.direct_sampling_mode = value

    @property
    def samples_to_send(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.samples_to_send
        else:
            raise ValueError("Unsupported Backend")

    @samples_to_send.setter
    def samples_to_send(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            self.__dev.init_send_parameters(value, self.num_sending_repeats)
        elif self.backend == Backends.network:
            self.__dev.samples_to_send = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def device_args(self):
        return self.__dev.device_args

    @device_args.setter
    def device_args(self, value):
        self.__dev.device_args = value

    @property
    def ip(self):
        if self.backend == Backends.grc:
            return self.__dev.device_ip
        elif self.backend == Backends.native:
            return self.__dev.device_ip
        else:
            raise ValueError("Unsupported Backend")

    @ip.setter
    def ip(self, value):
        if self.backend == Backends.grc:
            self.__dev.device_ip = value
        elif self.backend == Backends.native:
            self.__dev.device_ip = value
        elif self.backend in (Backends.none, Backends.network):
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def port(self):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            return self.__dev.port
        else:
            raise ValueError("Unsupported Backend")

    @port.setter
    def port(self, value):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            self.__dev.port = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def data(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.samples_to_send
            else:
                return self.__dev.receive_buffer
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                raise NotImplementedError("Todo")
            else:
                if self.__dev.raw_mode:
                    return self.__dev.receive_buffer
                else:
                    return self.__dev.received_bits
        else:
            raise ValueError("Unsupported Backend")

    @data.setter
    def data(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.samples_to_send = value
            else:
                self.__dev.receive_buffer = value
        else:
            logger.warning("{}:{} has no data".format(self.__class__.__name__,
                                                      self.backend.name))

    def free_data(self):
        if self.backend == Backends.grc:
            self.__dev.data = None
        elif self.backend == Backends.native:
            self.__dev.samples_to_send = None
            self.__dev.receive_buffer = None
        elif self.backend == Backends.network:
            self.__dev.free_data()
        elif self.backend == Backends.none:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def num_sending_repeats(self):
        if self.mode == Mode.send:
            if self.backend == Backends.grc:
                return self.__dev.max_repeats
            elif self.backend == Backends.native:
                return self.__dev.sending_repeats
            else:
                raise ValueError("Unsupported Backend")

    @num_sending_repeats.setter
    def num_sending_repeats(self, value):
        if self.mode == Mode.send:
            if self.backend == Backends.grc:
                if value != self.__dev.max_repeats:
                    self.__dev.max_repeats = value
                    self.__dev.current_iteration = 0
            elif self.backend in (Backends.native, Backends.network):
                self.__dev.sending_repeats = value
            else:
                raise ValueError("Unsupported Backend")

    @property
    def current_index(self):
        if self.backend == Backends.grc:
            return self.__dev.current_index
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_recv_index
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_receive_index
        else:
            raise ValueError("Unsupported Backend")

    @current_index.setter
    def current_index(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_index = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_recv_index = value
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_receive_index = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def current_iteration(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.current_sending_repeat
        else:
            raise ValueError("Unsupported Backend")

    @current_iteration.setter
    def current_iteration(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_iteration = value
        elif self.backend in (Backends.native, Backends.network):
            self.__dev.current_sending_repeat = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def sending_finished(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration is None
        elif self.backend == Backends.native:
            return self.__dev.sending_finished
        elif self.backend == Backends.network:
            return self.__dev.current_sent_sample == len(self.samples_to_send)
        else:
            raise ValueError("Unsupported Backend")

    @property
    def spectrum(self):
        if self.mode == Mode.spectrum:
            if self.backend == Backends.grc:
                return self.__dev.x, self.__dev.y
            elif self.backend == Backends.native or self.backend == Backends.network:
                w = np.abs(np.fft.fft(self.__dev.receive_buffer))
                freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate)
                idx = np.argsort(freqs)
                return freqs[idx].astype(np.float32), w[idx].astype(np.float32)
        else:
            raise ValueError("Spectrum x only available in spectrum mode")

    def start(self):
        if self.backend == Backends.grc:
            self.__dev.setTerminationEnabled(True)
            self.__dev.terminate()
            time.sleep(0.1)
            self.__dev.start(
            )  # Already connected to started signal in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.start_tx_mode(resume=True)
            else:
                self.__dev.start_rx_mode()

            self.emit_started_signal()
        elif self.backend == Backends.network:
            if self.mode == Mode.receive or self.mode == Mode.spectrum:
                self.__dev.start_tcp_server_for_receiving()
            else:
                self.__dev.start_raw_sending_thread()

            self.emit_started_signal()
        else:
            raise ValueError("Unsupported Backend")

    def stop(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.stop_tx_mode(msg)
            else:
                self.__dev.stop_rx_mode(msg)
            self.emit_stopped_signal()
        elif self.backend == Backends.network:
            self.__dev.stop_tcp_server()
            self.emit_stopped_signal()
        elif self.backend == Backends.none:
            pass
        else:
            logger.error("Stop device: Unsupported backend " +
                         str(self.backend))

    def stop_on_error(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            self.read_messages()  # Clear errors
            self.__dev.stop_rx_mode("Stop on error")
            self.__dev.stop_tx_mode("Stop on error")
            self.emit_stopped_signal()
        else:
            raise ValueError("Unsupported Backend")

    def cleanup(self):
        if self.backend == Backends.grc:
            if self.mode == Mode.send:
                self.__dev.socket.close()
                time.sleep(0.1)
            self.__dev.quit()
            self.data = None

        elif self.backend == Backends.native:
            self.data = None

        elif self.backend == Backends.none:
            pass

        else:
            raise ValueError("Unsupported Backend")

    def emit_stopped_signal(self):
        self.stopped.emit()

    def emit_started_signal(self):
        self.started.emit()

    def emit_sender_needs_restart(self):
        self.sender_needs_restart.emit()

    def emit_index_changed(self, old, new):
        self.index_changed.emit(old, new)

    def read_messages(self):
        if self.backend == Backends.grc:
            return self.__dev.read_errors()
        elif self.backend == Backends.native:
            messages = "\n".join(self.__dev.device_messages)
            if messages and not messages.endswith("\n"):
                messages += "\n"
            self.__dev.device_messages.clear()
            return messages
        elif self.backend == Backends.network:
            return ""
        else:
            raise ValueError("Unsupported Backend")

    def set_server_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.server_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")

    def set_client_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.client_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")

    def increase_gr_port(self):
        if self.backend == Backends.grc:
            self.__dev.gr_port += 1
            logger.info("Retry with port " + str(self.__dev.gr_port))
        else:
            raise ValueError("Only for GR backend")
示例#27
0
    def test_external_program_simulator(self):
        if sys.platform == "win32" and struct.calcsize("P") * 8 == 32:
            print("Skipping test on 32 Bit windows as CI is slow.")
            self.assertTrue(True)
            return

        stc = self.form.simulator_tab_controller  # type: SimulatorTabController
        stc.ui.btnAddParticipant.click()
        stc.ui.btnAddParticipant.click()

        stc.project_manager.simulator_timeout_ms = 999999999

        stc.simulator_scene.add_counter_action(None, 0)
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, CounterActionItem))
        action.model_item.start = 3
        action.model_item.step = 2
        counter_item_str = "item" + str(
            action.model_item.index()) + ".counter_value"

        stc.ui.gvSimulator.add_empty_message(42)
        stc.ui.gvSimulator.add_empty_message(42)

        stc.ui.cbViewType.setCurrentIndex(0)
        stc.create_simulator_label(0, 10, 20)
        stc.create_simulator_label(1, 10, 20)

        messages = stc.simulator_config.get_all_messages()
        messages[0].source = stc.project_manager.participants[0]
        messages[0].destination = stc.project_manager.participants[1]
        messages[0].destination.simulate = True
        messages[1].source = stc.project_manager.participants[1]
        messages[1].destination = stc.project_manager.participants[0]

        stc.simulator_scene.add_trigger_command_action(None, 200)
        stc.simulator_scene.add_sleep_action(None, 200)

        lbl1 = messages[0].message_type[0]  # type: SimulatorProtocolLabel
        lbl2 = messages[1].message_type[0]  # type: SimulatorProtocolLabel

        ext_program = get_path_for_data_file(
            "external_program_simulator.py") + " " + counter_item_str
        if sys.platform == "win32":
            ext_program = sys.executable + " " + ext_program

        lbl1.value_type_index = 3
        lbl1.external_program = ext_program
        lbl2.value_type_index = 3
        lbl2.external_program = ext_program

        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, SleepActionItem))
        action.model_item.sleep_time = 0.000000001
        stc.simulator_scene.clearSelection()
        action = next(item for item in stc.simulator_scene.items()
                      if isinstance(item, TriggerCommandActionItem))
        action.setSelected(True)
        self.assertEqual(stc.ui.detail_view_widget.currentIndex(), 4)
        file_name = os.path.join(tempfile.gettempdir(), "external_test")
        if os.path.isfile(file_name):
            os.remove(file_name)

        self.assertFalse(os.path.isfile(file_name))
        external_command = "cmd.exe /C copy NUL {}".format(
            file_name) if os.name == "nt" else "touch {}".format(file_name)
        stc.ui.lineEditTriggerCommand.setText(external_command)
        self.assertEqual(action.model_item.command, external_command)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = stc.get_simulator_dialog()
        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)

        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()

        while not any("Waiting for message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(self.TIMEOUT)

        conn, addr = s.accept()

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        self.alice.send_raw_data(modulator.modulate("100" + "10101010" * 42),
                                 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, 2 * self.num_zeros_for_pause), 1)

        while not any("Sending message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message")
            time.sleep(self.TIMEOUT)

        time.sleep(self.TIMEOUT)
        bits = self.__demodulate(conn)
        self.assertEqual(bits[0].rstrip("0"), "101010101")

        while simulator.is_simulating:
            logger.debug("Wait for simulator to finish")
            time.sleep(self.TIMEOUT)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)

        self.assertTrue(os.path.isfile(file_name))
示例#28
0
    def __init__(self, backend_handler, name: str, mode: Mode, freq=None, sample_rate=None, bandwidth=None,
                 gain=None, if_gain=None, baseband_gain=None, samples_to_send=None,
                 device_ip=None, sending_repeats=1, parent=None, resume_on_full_receive_buffer=False, raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        resume_on_full_receive_buffer = self.mode == Mode.spectrum or resume_on_full_receive_buffer

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent, resume_on_full_receive_buffer=resume_on_full_receive_buffer)
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(samples_to_send) if samples_to_send is not None else 2 ** 15
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq, gain, sample_rate, device_number=0,
                                        resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq, gain, sample_rate, bandwidth, device_number=0,
                                           resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name == "limesdr":
                    from urh.dev.native.LimeSDR import LimeSDR
                    self.__dev = LimeSDR(freq, gain, sample_rate, bandwidth, gain,
                                         resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("airspy"):
                    from urh.dev.native.AirSpy import AirSpy
                    self.__dev = AirSpy(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                        resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("usrp"):
                    from urh.dev.native.USRP import USRP
                    self.__dev = USRP(freq, gain, sample_rate, bandwidth, gain,
                                      resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name.startswith("sdrplay"):
                    from urh.dev.native.SDRPlay import SDRPlay
                    self.__dev = SDRPlay(freq, gain, bandwidth, gain, if_gain=if_gain,
                                         resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                elif name == "soundcard":
                    from urh.dev.native.SoundCard import SoundCard
                    self.__dev = SoundCard(sample_rate, resume_on_full_receive_buffer=resume_on_full_receive_buffer)
                else:
                    raise NotImplementedError("Native Backend for {0} not yet implemented".format(name))

            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain, if_gain, baseband_gain,
                                    resume_on_full_receive_buffer)
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send, sending_repeats)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(raw_mode=raw_mode,
                                                   resume_on_full_receive_buffer=resume_on_full_receive_buffer,
                                                   spectrum=self.mode == Mode.spectrum, sending=self.mode == Mode.send)
            self.__dev.send_connection_established.connect(self.emit_ready_for_action)
            self.__dev.receive_server_started.connect(self.emit_ready_for_action)
            self.__dev.error_occurred.connect(self.emit_fatal_error_occurred)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

        if hasattr(self.__dev, "data_received"):
            self.__dev.data_received.connect(self.data_received.emit)

        if mode == Mode.spectrum:
            self.__dev.is_in_spectrum_mode = True
示例#29
0
    def test_simulation_flow(self):
        """
        test a simulation flow with an increasing sequence number

        :return:
        """
        if sys.platform == "win32" and struct.calcsize("P") * 8 == 32:
            print("Skipping test on 32 Bit windows as CI is slow.")
            self.assertTrue(True)
            return

        profile = self.get_path_for_filename("testprofile.sim.xml")
        self.form.add_files([profile])
        self.assertEqual(
            len(self.form.simulator_tab_controller.simulator_scene.
                get_all_message_items()), 6)

        port = self.get_free_port()
        self.alice = NetworkSDRInterfacePlugin(raw_mode=True)
        self.alice.client_port = port

        dialog = self.form.simulator_tab_controller.get_simulator_dialog(
        )  # type: SimulatorDialog
        dialog.project_manager.simulator_timeout_ms = 999999999

        name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(name)
        dialog.device_settings_tx_widget.ui.cbDevice.setCurrentText(name)
        simulator = dialog.simulator
        simulator.sniffer.rcv_device.set_server_port(port)

        port = self.get_free_port()
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        s.bind(("", port))
        s.listen(1)

        simulator.sender.device.set_client_port(port)
        dialog.ui.btnStartStop.click()

        while not any("Waiting for message" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message")
            time.sleep(self.TIMEOUT)

        conn, addr = s.accept()

        msg = next(msg for msg in dialog.simulator_config.get_all_messages()
                   if msg.source.name == "Alice")
        checksum_label = next(
            lbl for lbl in msg.message_type
            if lbl.is_checksum_label).label  # type: ChecksumLabel

        modulator = dialog.project_manager.modulators[0]  # type: Modulator

        preamble_str = "10101010"
        sync_str = "1001"
        preamble = list(map(int, preamble_str))
        sync = list(map(int, sync_str))
        seq = list(map(int, "00000010"))
        data = list(map(int, "11001101"))

        seq_num = int("".join(map(str, seq)), 2)

        checksum = list(checksum_label.calculate_checksum(seq + data))

        msg1 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg1), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 2" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 2")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str), msg=bits)
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 1)

        seq = list(map(int, "{0:08b}".format(seq_num + 2)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg2 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg2), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 4" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 4")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)
        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 3)

        seq = list(map(int, "{0:08b}".format(seq_num + 4)))
        checksum = list(checksum_label.calculate_checksum(seq + data))
        msg3 = preamble + sync + seq + data + checksum

        self.alice.send_raw_data(modulator.modulate(msg3), 1)
        time.sleep(self.TIMEOUT)
        self.alice.send_raw_data(
            IQArray(None, np.float32, self.num_zeros_for_pause), 1)

        while not any("Sending message 6" in msg
                      for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to send message 6")
            time.sleep(self.TIMEOUT)

        bits = self.__demodulate(conn)

        self.assertEqual(len(bits), 1)

        bits = bits[0]
        self.assertTrue(bits.startswith(preamble_str + sync_str))
        bits = bits.replace(preamble_str + sync_str, "")
        self.assertEqual(int(bits, 2), seq_num + 5)

        NetworkSDRInterfacePlugin.shutdown_socket(conn)
        NetworkSDRInterfacePlugin.shutdown_socket(s)
示例#30
0
class VirtualDevice(QObject):
    """
    Wrapper class for providing sending methods for grc and native devices

    """
    started = pyqtSignal()
    stopped = pyqtSignal()
    sender_needs_restart = pyqtSignal()

    fatal_error_occurred = pyqtSignal(str)
    ready_for_action = pyqtSignal()

    data_received = pyqtSignal(
        np.ndarray)  # for direct demodulation in sniffer

    continuous_send_msg = "Continuous send mode is not supported for GNU Radio backend. " \
                          "You can change the configured device backend in options."

    def __init__(self,
                 backend_handler,
                 name: str,
                 mode: Mode,
                 freq=None,
                 sample_rate=None,
                 bandwidth=None,
                 gain=None,
                 if_gain=None,
                 baseband_gain=None,
                 samples_to_send=None,
                 device_ip=None,
                 sending_repeats=1,
                 parent=None,
                 resume_on_full_receive_buffer=False,
                 raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        resume_on_full_receive_buffer = self.mode == Mode.spectrum or resume_on_full_receive_buffer

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[
                    name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(
                    freq,
                    sample_rate,
                    bandwidth,
                    gain,
                    if_gain,
                    baseband_gain,
                    parent=parent,
                    resume_on_full_receive_buffer=resume_on_full_receive_buffer
                )
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq,
                                          sample_rate,
                                          bandwidth,
                                          gain,
                                          if_gain,
                                          baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(
                    samples_to_send) if samples_to_send is not None else 2**15
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq,
                                            sample_rate,
                                            bandwidth,
                                            gain,
                                            if_gain,
                                            baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(
                self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain,
                                        if_gain, baseband_gain,
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq,
                                        gain,
                                        sample_rate,
                                        device_number=0,
                                        resume_on_full_receive_buffer=
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq,
                                           gain,
                                           sample_rate,
                                           bandwidth,
                                           device_number=0,
                                           resume_on_full_receive_buffer=
                                           resume_on_full_receive_buffer)
                elif name == "limesdr":
                    from urh.dev.native.LimeSDR import LimeSDR
                    self.__dev = LimeSDR(freq,
                                         gain,
                                         sample_rate,
                                         bandwidth,
                                         gain,
                                         resume_on_full_receive_buffer=
                                         resume_on_full_receive_buffer)
                elif name.startswith("airspy"):
                    from urh.dev.native.AirSpy import AirSpy
                    self.__dev = AirSpy(freq,
                                        sample_rate,
                                        bandwidth,
                                        gain,
                                        if_gain,
                                        baseband_gain,
                                        resume_on_full_receive_buffer=
                                        resume_on_full_receive_buffer)
                elif name.startswith("usrp"):
                    from urh.dev.native.USRP import USRP
                    self.__dev = USRP(freq,
                                      gain,
                                      sample_rate,
                                      bandwidth,
                                      gain,
                                      resume_on_full_receive_buffer=
                                      resume_on_full_receive_buffer)
                elif name.startswith("sdrplay"):
                    from urh.dev.native.SDRPlay import SDRPlay
                    self.__dev = SDRPlay(freq,
                                         gain,
                                         bandwidth,
                                         gain,
                                         if_gain=if_gain,
                                         resume_on_full_receive_buffer=
                                         resume_on_full_receive_buffer)
                elif name == "soundcard":
                    from urh.dev.native.SoundCard import SoundCard
                    self.__dev = SoundCard(sample_rate,
                                           resume_on_full_receive_buffer=
                                           resume_on_full_receive_buffer)
                else:
                    raise NotImplementedError(
                        "Native Backend for {0} not yet implemented".format(
                            name))

            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain,
                                    if_gain, baseband_gain,
                                    resume_on_full_receive_buffer)
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send,
                                                sending_repeats)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(
                raw_mode=raw_mode,
                resume_on_full_receive_buffer=resume_on_full_receive_buffer,
                spectrum=self.mode == Mode.spectrum,
                sending=self.mode == Mode.send)
            self.__dev.send_connection_established.connect(
                self.emit_ready_for_action)
            self.__dev.receive_server_started.connect(
                self.emit_ready_for_action)
            self.__dev.error_occurred.connect(self.emit_fatal_error_occurred)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

        if hasattr(self.__dev, "data_received"):
            self.__dev.data_received.connect(self.data_received.emit)

        if mode == Mode.spectrum:
            self.__dev.is_in_spectrum_mode = True

    @property
    def has_multi_device_support(self):
        return hasattr(
            self.__dev,
            "has_multi_device_support") and self.__dev.has_multi_device_support

    @property
    def device_serial(self):
        if hasattr(self.__dev, "device_serial"):
            return self.__dev.device_serial
        else:
            return None

    @device_serial.setter
    def device_serial(self, value):
        if hasattr(self.__dev, "device_serial"):
            self.__dev.device_serial = value

    @property
    def device_number(self):
        if hasattr(self.__dev, "device_number"):
            return self.__dev.device_number
        else:
            return None

    @device_number.setter
    def device_number(self, value):
        if hasattr(self.__dev, "device_number"):
            self.__dev.device_number = value

    @property
    def bandwidth(self):
        return self.__dev.bandwidth

    @bandwidth.setter
    def bandwidth(self, value):
        self.__dev.bandwidth = value

    @property
    def bandwidth_is_adjustable(self):
        if self.backend == Backends.grc:
            return True
        elif self.backend == Backends.native:
            return self.__dev.bandwidth_is_adjustable
        elif self.backend == Backends.network:
            return True
        else:
            raise ValueError("Unsupported Backend")

    @property
    def frequency(self):
        if self.backend == Backends.grc:
            return self.__dev.freq
        elif self.backend == Backends.native:
            return self.__dev.frequency
        else:
            raise ValueError("Unsupported Backend")

    @frequency.setter
    def frequency(self, value):
        if self.backend == Backends.grc:
            self.__dev.freq = value
        elif self.backend == Backends.native:
            self.__dev.frequency = value
        elif self.backend == Backends.network:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def num_samples_to_send(self) -> int:
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.num_samples_to_send
        else:
            raise ValueError(self.continuous_send_msg)

    @num_samples_to_send.setter
    def num_samples_to_send(self, value: int):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.num_samples_to_send = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_send_continuous(self) -> bool:
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.sending_is_continuous
        else:
            raise ValueError(self.continuous_send_msg)

    @is_send_continuous.setter
    def is_send_continuous(self, value: bool):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.sending_is_continuous = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_raw_mode(self) -> bool:
        if self.backend == Backends.network:
            return self.__dev.raw_mode
        else:
            return True

    @property
    def continuous_send_ring_buffer(self):
        if self.backend in (Backends.native, Backends.network):
            return self.__dev.continuous_send_ring_buffer
        else:
            raise ValueError(self.continuous_send_msg)

    @continuous_send_ring_buffer.setter
    def continuous_send_ring_buffer(self, value):
        if self.backend in (Backends.native, Backends.network):
            self.__dev.continuous_send_ring_buffer = value
        else:
            raise ValueError(self.continuous_send_msg)

    @property
    def is_in_spectrum_mode(self):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            return self.__dev.is_in_spectrum_mode
        else:
            raise ValueError("Unsupported Backend")

    @is_in_spectrum_mode.setter
    def is_in_spectrum_mode(self, value: bool):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            self.__dev.is_in_spectrum_mode = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def gain(self):
        return self.__dev.gain

    @gain.setter
    def gain(self, value):
        try:
            self.__dev.gain = value
        except AttributeError as e:
            logger.warning(str(e))

    @property
    def if_gain(self):
        try:
            return self.__dev.if_gain
        except AttributeError as e:
            logger.warning(str(e))

    @if_gain.setter
    def if_gain(self, value):
        try:
            self.__dev.if_gain = value
        except AttributeError as e:
            logger.warning(str(e))

    @property
    def baseband_gain(self):
        return self.__dev.baseband_gain

    @baseband_gain.setter
    def baseband_gain(self, value):
        self.__dev.baseband_gain = value

    @property
    def sample_rate(self):
        return self.__dev.sample_rate

    @sample_rate.setter
    def sample_rate(self, value):
        self.__dev.sample_rate = value

    @property
    def channel_index(self) -> int:
        return self.__dev.channel_index

    @channel_index.setter
    def channel_index(self, value: int):
        self.__dev.channel_index = value

    @property
    def antenna_index(self) -> int:
        return self.__dev.antenna_index

    @antenna_index.setter
    def antenna_index(self, value: int):
        self.__dev.antenna_index = value

    @property
    def freq_correction(self):
        return self.__dev.freq_correction

    @freq_correction.setter
    def freq_correction(self, value):
        self.__dev.freq_correction = value

    @property
    def direct_sampling_mode(self) -> int:
        return self.__dev.direct_sampling_mode

    @direct_sampling_mode.setter
    def direct_sampling_mode(self, value):
        self.__dev.direct_sampling_mode = value

    @property
    def emit_data_received_signal(self):
        return self.__dev.emit_data_received_signal

    @emit_data_received_signal.setter
    def emit_data_received_signal(self, value):
        self.__dev.emit_data_received_signal = value

    @property
    def samples_to_send(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.samples_to_send
        else:
            raise ValueError("Unsupported Backend")

    @samples_to_send.setter
    def samples_to_send(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            self.__dev.init_send_parameters(value, self.num_sending_repeats)
        elif self.backend == Backends.network:
            self.__dev.samples_to_send = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def ip(self):
        if self.backend == Backends.grc:
            return self.__dev.device_ip
        elif self.backend == Backends.native:
            return self.__dev.device_ip
        else:
            raise ValueError("Unsupported Backend")

    @ip.setter
    def ip(self, value):
        if self.backend == Backends.grc:
            self.__dev.device_ip = value
        elif self.backend == Backends.native:
            self.__dev.device_ip = value
        elif self.backend in (Backends.none, Backends.network):
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def port(self):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            return self.__dev.port
        else:
            raise ValueError("Unsupported Backend")

    @port.setter
    def port(self, value):
        if self.backend in (Backends.grc, Backends.native, Backends.network):
            self.__dev.port = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def data(self):
        if self.backend == Backends.grc:
            return self.__dev.data
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.samples_to_send
            else:
                return self.__dev.receive_buffer
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                raise NotImplementedError("Todo")
            else:
                if self.__dev.raw_mode:
                    return self.__dev.receive_buffer
                else:
                    return self.__dev.received_bits
        else:
            raise ValueError("Unsupported Backend")

    @data.setter
    def data(self, value):
        if self.backend == Backends.grc:
            self.__dev.data = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.samples_to_send = value
            else:
                self.__dev.receive_buffer = value
        else:
            logger.warning("{}:{} has no data".format(self.__class__.__name__,
                                                      self.backend.name))

    def free_data(self):
        if self.backend == Backends.grc:
            self.__dev.data = None
        elif self.backend == Backends.native:
            self.__dev.samples_to_send = None
            self.__dev.receive_buffer = None
        elif self.backend == Backends.network:
            self.__dev.free_data()
        elif self.backend == Backends.none:
            pass
        else:
            raise ValueError("Unsupported Backend")

    @property
    def resume_on_full_receive_buffer(self) -> bool:
        return self.__dev.resume_on_full_receive_buffer

    @resume_on_full_receive_buffer.setter
    def resume_on_full_receive_buffer(self, value: bool):
        if value != self.__dev.resume_on_full_receive_buffer:
            self.__dev.resume_on_full_receive_buffer = value
            if self.backend == Backends.native:
                self.__dev.receive_buffer = None
            elif self.backend == Backends.grc:
                self.__dev.data = None

    @property
    def num_sending_repeats(self):
        return self.__dev.sending_repeats

    @num_sending_repeats.setter
    def num_sending_repeats(self, value):
        self.__dev.sending_repeats = value

    @property
    def current_index(self):
        if self.backend == Backends.grc:
            return self.__dev.current_index
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_recv_index
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                return self.__dev.current_sent_sample
            else:
                return self.__dev.current_receive_index
        else:
            raise ValueError("Unsupported Backend")

    @current_index.setter
    def current_index(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_index = value
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_recv_index = value
        elif self.backend == Backends.network:
            if self.mode == Mode.send:
                self.__dev.current_sent_sample = value
            else:
                self.__dev.current_receive_index = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def current_iteration(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.current_sending_repeat
        else:
            raise ValueError("Unsupported Backend")

    @current_iteration.setter
    def current_iteration(self, value):
        if self.backend == Backends.grc:
            self.__dev.current_iteration = value
        elif self.backend in (Backends.native, Backends.network):
            self.__dev.current_sending_repeat = value
        else:
            raise ValueError("Unsupported Backend")

    @property
    def sending_finished(self):
        if self.backend == Backends.grc:
            return self.__dev.current_iteration is None
        elif self.backend in (Backends.native, Backends.network):
            return self.__dev.sending_finished
        else:
            raise ValueError("Unsupported Backend")

    @property
    def spectrum(self):
        if self.mode == Mode.spectrum:
            if self.backend == Backends.grc:
                return self.__dev.x, self.__dev.y
            elif self.backend == Backends.native or self.backend == Backends.network:
                w = np.abs(np.fft.fft(self.__dev.receive_buffer))
                freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate)
                idx = np.argsort(freqs)
                return freqs[idx].astype(np.float32), w[idx].astype(np.float32)
        else:
            raise ValueError("Spectrum x only available in spectrum mode")

    def start(self):
        if self.backend == Backends.grc:
            self.__dev.setTerminationEnabled(True)
            self.__dev.terminate()
            time.sleep(0.1)
            self.__dev.start(
            )  # Already connected to started signal in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.start_tx_mode(resume=True)
            else:
                self.__dev.start_rx_mode()

            self.emit_started_signal()
        elif self.backend == Backends.network:
            if self.mode == Mode.receive or self.mode == Mode.spectrum:
                self.__dev.start_tcp_server_for_receiving()
            else:
                self.__dev.start_raw_sending_thread()

            self.emit_started_signal()
        else:
            raise ValueError("Unsupported Backend")

    def stop(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            if self.mode == Mode.send:
                self.__dev.stop_tx_mode(msg)
            else:
                self.__dev.stop_rx_mode(msg)
            self.emit_stopped_signal()
        elif self.backend == Backends.network:
            self.__dev.stop_tcp_server()
            self.__dev.stop_sending_thread()
            self.emit_stopped_signal()
        elif self.backend == Backends.none:
            pass
        else:
            logger.error("Stop device: Unsupported backend " +
                         str(self.backend))

    def stop_on_error(self, msg: str):
        if self.backend == Backends.grc:
            self.__dev.stop(msg)  # Already connected to stopped in constructor
        elif self.backend == Backends.native:
            self.read_messages()  # Clear errors
            self.__dev.stop_rx_mode("Stop on error")
            self.__dev.stop_tx_mode("Stop on error")
            self.emit_stopped_signal()
        else:
            raise ValueError("Unsupported Backend")

    def cleanup(self):
        if self.backend == Backends.grc:
            if self.mode == Mode.send:
                self.__dev.socket.close()
                time.sleep(0.1)
            self.__dev.quit()
            self.data = None

        elif self.backend == Backends.native:
            self.data = None

        elif self.backend == Backends.none:
            pass

        else:
            raise ValueError("Unsupported Backend")

    def emit_stopped_signal(self):
        self.stopped.emit()

    def emit_started_signal(self):
        self.started.emit()

    def emit_sender_needs_restart(self):
        self.sender_needs_restart.emit()

    def read_messages(self) -> str:
        """
        returns a string of new device messages separated by newlines

        :return:
        """
        if self.backend == Backends.grc:
            errors = self.__dev.read_errors()

            if "FATAL: " in errors:
                self.fatal_error_occurred.emit(
                    errors[errors.index("FATAL: "):])

            return errors
        elif self.backend == Backends.native:
            messages = "\n".join(self.__dev.device_messages)
            self.__dev.device_messages.clear()

            if messages and not messages.endswith("\n"):
                messages += "\n"

            if "successfully started" in messages:
                self.ready_for_action.emit()
            elif "failed to start" in messages:
                self.fatal_error_occurred.emit(
                    messages[messages.index("failed to start"):])

            return messages
        elif self.backend == Backends.network:
            return ""
        else:
            raise ValueError("Unsupported Backend")

    def set_server_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.server_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")

    def set_client_port(self, port: int):
        if self.backend == Backends.network:
            self.__dev.client_port = port
        else:
            raise ValueError(
                "Setting port only supported for NetworkSDR Plugin")

    def get_device_list(self):
        if hasattr(self.__dev, "get_device_list"):
            return self.__dev.get_device_list()
        else:
            return []

    def increase_gr_port(self):
        if self.backend == Backends.grc:
            self.__dev.gr_port += 1
            logger.info("Retry with port " + str(self.__dev.gr_port))
        else:
            raise ValueError("Only for GR backend")

    def emit_ready_for_action(self):
        """
        Notify observers that device is successfully initialized
        :return:
        """
        self.ready_for_action.emit()

    def emit_fatal_error_occurred(self, msg: str):
        self.fatal_error_occurred.emit(msg)
示例#31
0
    def test_performance(self):
        self.form = MainController()
        self.cfc = self.form.compare_frame_controller
        self.stc = self.form.simulator_tab_controller
        self.gtc = self.form.generator_tab_controller

        self.form.add_signalfile(get_path_for_data_file("esaver.complex16s"))
        self.sframe = self.form.signal_tab_controller.signal_frames[0]
        self.sim_frame = self.form.simulator_tab_controller
        self.form.ui.tabWidget.setCurrentIndex(3)
        self.cfc.proto_analyzer.auto_assign_labels()

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(raw_mode=True)

        part_a = Participant("Device A", shortname="A", color_index=0)
        part_b = Participant("Device B", shortname="B", color_index=1)
        part_b.simulate = True

        self.form.project_manager.participants.append(part_a)
        self.form.project_manager.participants.append(part_b)
        self.form.project_manager.project_updated.emit()

        sniffer = ProtocolSniffer(100, 0.01, 0.01, 0.1, 5, "FSK", 1,
                                  NetworkSDRInterfacePlugin.NETWORK_SDR_NAME, BackendHandler(),
                                  network_raw_mode=True)
        sender = EndlessSender(BackendHandler(), NetworkSDRInterfacePlugin.NETWORK_SDR_NAME)

        simulator = Simulator(self.stc.simulator_config, self.gtc.modulators, self.stc.sim_expression_parser,
                              self.form.project_manager, sniffer=sniffer, sender=sender)

        pause = 100
        msg_a = SimulatorMessage(part_b,
                                 [1, 0] * 16 + [1, 1, 0, 0] * 8 + [0, 0, 1, 1] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 pause=pause, message_type=MessageType("empty_message_type"), source=part_a)

        msg_b = SimulatorMessage(part_a,
                                 [1, 0] * 16 + [1, 1, 0, 0] * 8 + [1, 1, 0, 0] * 8 + [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 pause=pause, message_type=MessageType("empty_message_type"), source=part_b)

        self.stc.simulator_config.add_items([msg_a, msg_b], 0, None)
        self.stc.simulator_config.update_active_participants()

        port = self.get_free_port()
        sniffer = simulator.sniffer
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender.client_port = port

        sender = simulator.sender
        port = self.get_free_port()
        sender.device.set_client_port(port)
        sender.device._VirtualDevice__dev.name = "simulator_sender"

        current_index = Value("L")
        elapsed = Value("f")
        target_num_samples = 13600 + pause
        receive_process = Process(target=receive, args=(port, current_index, target_num_samples, elapsed))
        receive_process.daemon = True
        receive_process.start()

        # Ensure receiver is running
        time.sleep(2)

        # spy = QSignalSpy(self.network_sdr_plugin_receiver.rcv_index_changed)
        simulator.start()

        modulator = Modulator("test_modulator")
        modulator.samples_per_symbol = 100
        modulator.carrier_freq_hz = 55e3

        # yappi.start()

        self.network_sdr_plugin_sender.send_raw_data(modulator.modulate(msg_a.encoded_bits), 1)
        time.sleep(0.5)
        # send some zeros to simulate the end of a message
        self.network_sdr_plugin_sender.send_raw_data(np.zeros(self.num_zeros_for_pause, dtype=np.complex64), 1)
        time.sleep(0.5)
        receive_process.join(15)

        logger.info("PROCESS TIME: {0:.2f}ms".format(elapsed.value))

        # self.assertEqual(current_index.value, target_num_samples)
        self.assertLess(elapsed.value, 200)

        # timeout = spy.wait(2000)
        # yappi.get_func_stats().print_all()
        # yappi.get_thread_stats().print_all()
示例#32
0
class TestSimulator(QtTestCase):
    def setUp(self):
        self.form = MainController()
        self.cfc = self.form.compare_frame_controller
        self.stc = self.form.simulator_tab_controller
        self.gtc = self.form.generator_tab_controller

        self.form.add_signalfile(get_path_for_data_file("esaver.complex"))
        self.sframe = self.form.signal_tab_controller.signal_frames[0]
        self.sim_frame = self.form.simulator_tab_controller
        self.form.ui.tabWidget.setCurrentIndex(3)
        self.cfc.proto_analyzer.auto_assign_labels()

        SettingsProxy.OVERWRITE_RECEIVE_BUFFER_SIZE = 100 * 10**6

        self.network_sdr_plugin_sender = NetworkSDRInterfacePlugin(
            raw_mode=True)

    def test_performance(self):
        part_a = Participant("Device A", shortname="A", color_index=0)
        part_b = Participant("Device B", shortname="B", color_index=1)
        part_b.simulate = True

        self.form.project_manager.participants.append(part_a)
        self.form.project_manager.participants.append(part_b)
        self.form.project_manager.project_updated.emit()

        sniffer = ProtocolSniffer(100,
                                  0.01,
                                  0.001,
                                  5,
                                  1,
                                  NetworkSDRInterfacePlugin.NETWORK_SDR_NAME,
                                  BackendHandler(),
                                  network_raw_mode=True,
                                  real_time=True)
        sender = EndlessSender(BackendHandler(),
                               NetworkSDRInterfacePlugin.NETWORK_SDR_NAME)

        simulator = Simulator(self.stc.simulator_config,
                              self.gtc.modulators,
                              self.stc.sim_expression_parser,
                              self.form.project_manager,
                              sniffer=sniffer,
                              sender=sender)

        msg_a = SimulatorMessage(part_b, [1, 0] * 16 + [1, 1, 0, 0] * 8 +
                                 [0, 0, 1, 1] * 8 +
                                 [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 100000,
                                 MessageType("empty_message_type"),
                                 source=part_a)

        msg_b = SimulatorMessage(part_a, [1, 0] * 16 + [1, 1, 0, 0] * 8 +
                                 [1, 1, 0, 0] * 8 +
                                 [1, 0, 1, 1, 1, 0, 0, 1, 1, 1] * 4,
                                 100000,
                                 MessageType("empty_message_type"),
                                 source=part_b)

        self.stc.simulator_config.add_items([msg_a, msg_b], 0, None)
        self.stc.simulator_config.update_active_participants()

        port = self.__get_free_port()
        sniffer = simulator.sniffer
        sniffer.rcv_device.set_server_port(port)

        self.network_sdr_plugin_sender.client_port = port

        sender = simulator.sender
        port = self.__get_free_port()
        sender.device.set_client_port(port)
        sender.device._VirtualDevice__dev.name = "simulator_sender"

        current_index = Value("L")
        elapsed = Value("f")
        target_num_samples = 113600
        receive_process = Process(target=receive,
                                  args=(port, current_index,
                                        target_num_samples, elapsed))
        receive_process.daemon = True
        receive_process.start()

        # Ensure receiver is running
        time.sleep(1)

        # spy = QSignalSpy(self.network_sdr_plugin_receiver.rcv_index_changed)
        simulator.start()

        modulator = Modulator("test_modulator")
        modulator.samples_per_bit = 100
        modulator.carrier_freq_hz = 55e3
        modulator.modulate(msg_a.encoded_bits)

        # yappi.start()

        self.network_sdr_plugin_sender.send_raw_data(
            modulator.modulated_samples, 1)
        QTest.qWait(100)
        receive_process.join(10)

        print("PROCESS TIME: {0:.2f}ms".format(elapsed.value))

        self.assertEqual(current_index.value, target_num_samples)
        self.assertLess(elapsed.value, 200)

        # timeout = spy.wait(2000)
        # yappi.get_func_stats().print_all()
        # yappi.get_thread_stats().print_all()

    def __get_free_port(self):
        import socket
        s = socket.socket()
        s.bind(("", 0))
        port = s.getsockname()[1]
        s.close()
        return port
示例#33
0
    def __init__(self,
                 backend_handler,
                 name: str,
                 mode: Mode,
                 freq=None,
                 sample_rate=None,
                 bandwidth=None,
                 gain=None,
                 if_gain=None,
                 baseband_gain=None,
                 samples_to_send=None,
                 device_ip=None,
                 sending_repeats=1,
                 parent=None,
                 resume_on_full_receive_buffer=False,
                 raw_mode=True,
                 portnumber=1234):
        super().__init__(parent)
        self.name = name
        self.mode = mode
        self.backend_handler = backend_handler

        freq = config.DEFAULT_FREQUENCY if freq is None else freq
        sample_rate = config.DEFAULT_SAMPLE_RATE if sample_rate is None else sample_rate
        bandwidth = config.DEFAULT_BANDWIDTH if bandwidth is None else bandwidth
        gain = config.DEFAULT_GAIN if gain is None else gain
        if_gain = config.DEFAULT_IF_GAIN if if_gain is None else if_gain
        baseband_gain = config.DEFAULT_BB_GAIN if baseband_gain is None else baseband_gain

        resume_on_full_receive_buffer = self.mode == Mode.spectrum or resume_on_full_receive_buffer

        if self.name == NetworkSDRInterfacePlugin.NETWORK_SDR_NAME:
            self.backend = Backends.network
        else:
            try:
                self.backend = self.backend_handler.device_backends[
                    name.lower()].selected_backend
            except KeyError:
                logger.warning("Invalid device name: {0}".format(name))
                self.backend = Backends.none
                self.__dev = None
                return

        if self.backend == Backends.grc:
            if mode == Mode.receive:
                from urh.dev.gr.ReceiverThread import ReceiverThread
                self.__dev = ReceiverThread(
                    freq,
                    sample_rate,
                    bandwidth,
                    gain,
                    if_gain,
                    baseband_gain,
                    parent=parent,
                    resume_on_full_receive_buffer=resume_on_full_receive_buffer
                )
            elif mode == Mode.send:
                from urh.dev.gr.SenderThread import SenderThread
                self.__dev = SenderThread(freq,
                                          sample_rate,
                                          bandwidth,
                                          gain,
                                          if_gain,
                                          baseband_gain,
                                          parent=parent)
                self.__dev.data = samples_to_send
                self.__dev.samples_per_transmission = len(
                    samples_to_send) if samples_to_send is not None else 2**15
            elif mode == Mode.spectrum:
                from urh.dev.gr.SpectrumThread import SpectrumThread
                self.__dev = SpectrumThread(freq,
                                            sample_rate,
                                            bandwidth,
                                            gain,
                                            if_gain,
                                            baseband_gain,
                                            parent=parent)
            else:
                raise ValueError("Unknown mode")
            self.__dev.device = name
            self.__dev.started.connect(self.emit_started_signal)
            self.__dev.stopped.connect(self.emit_stopped_signal)
            self.__dev.sender_needs_restart.connect(
                self.emit_sender_needs_restart)
        elif self.backend == Backends.native:
            name = self.name.lower()
            if name in map(str.lower, BackendHandler.DEVICE_NAMES):
                if name == "hackrf":
                    from urh.dev.native.HackRF import HackRF
                    self.__dev = HackRF(freq, sample_rate, bandwidth, gain,
                                        if_gain, baseband_gain,
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtlsdr":
                    from urh.dev.native.RTLSDR import RTLSDR
                    self.__dev = RTLSDR(freq,
                                        gain,
                                        sample_rate,
                                        device_number=0,
                                        resume_on_full_receive_buffer=
                                        resume_on_full_receive_buffer)
                elif name.replace("-", "") == "rtltcp":
                    from urh.dev.native.RTLSDRTCP import RTLSDRTCP
                    self.__dev = RTLSDRTCP(freq,
                                           gain,
                                           sample_rate,
                                           bandwidth,
                                           device_number=0,
                                           resume_on_full_receive_buffer=
                                           resume_on_full_receive_buffer)
                elif name == "limesdr":
                    from urh.dev.native.LimeSDR import LimeSDR
                    self.__dev = LimeSDR(freq,
                                         gain,
                                         sample_rate,
                                         bandwidth,
                                         gain,
                                         resume_on_full_receive_buffer=
                                         resume_on_full_receive_buffer)
                elif name.startswith("airspy"):
                    from urh.dev.native.AirSpy import AirSpy
                    self.__dev = AirSpy(freq,
                                        sample_rate,
                                        bandwidth,
                                        gain,
                                        if_gain,
                                        baseband_gain,
                                        resume_on_full_receive_buffer=
                                        resume_on_full_receive_buffer)
                elif name.startswith("usrp"):
                    from urh.dev.native.USRP import USRP
                    self.__dev = USRP(freq,
                                      gain,
                                      sample_rate,
                                      bandwidth,
                                      gain,
                                      resume_on_full_receive_buffer=
                                      resume_on_full_receive_buffer)
                elif name.startswith("sdrplay"):
                    from urh.dev.native.SDRPlay import SDRPlay
                    self.__dev = SDRPlay(freq,
                                         gain,
                                         bandwidth,
                                         gain,
                                         if_gain=if_gain,
                                         resume_on_full_receive_buffer=
                                         resume_on_full_receive_buffer)
                elif name == "soundcard":
                    from urh.dev.native.SoundCard import SoundCard
                    self.__dev = SoundCard(sample_rate,
                                           resume_on_full_receive_buffer=
                                           resume_on_full_receive_buffer)
                else:
                    raise NotImplementedError(
                        "Native Backend for {0} not yet implemented".format(
                            name))

            elif name == "test":
                # For Unittests Only
                self.__dev = Device(freq, sample_rate, bandwidth, gain,
                                    if_gain, baseband_gain,
                                    resume_on_full_receive_buffer)
            else:
                raise ValueError("Unknown device name {0}".format(name))
            self.__dev.portnumber = portnumber
            self.__dev.device_ip = device_ip
            if mode == Mode.send:
                self.__dev.init_send_parameters(samples_to_send,
                                                sending_repeats)
        elif self.backend == Backends.network:
            self.__dev = NetworkSDRInterfacePlugin(
                raw_mode=raw_mode,
                resume_on_full_receive_buffer=resume_on_full_receive_buffer,
                spectrum=self.mode == Mode.spectrum,
                sending=self.mode == Mode.send)
            self.__dev.send_connection_established.connect(
                self.emit_ready_for_action)
            self.__dev.receive_server_started.connect(
                self.emit_ready_for_action)
            self.__dev.error_occurred.connect(self.emit_fatal_error_occurred)
            self.__dev.samples_to_send = samples_to_send
        elif self.backend == Backends.none:
            self.__dev = None
        else:
            raise ValueError("Unsupported Backend")

        if hasattr(self.__dev, "data_received"):
            self.__dev.data_received.connect(self.data_received.emit)

        if mode == Mode.spectrum:
            self.__dev.is_in_spectrum_mode = True
示例#34
0
    def test_open_simulator_dialog_and_send_mismatching_message(self):
        stc = self.form.simulator_tab_controller
        assert isinstance(stc, SimulatorTabController)

        self.__setup_project()
        self.add_all_signals_to_simulator()

        stc.simulator_scene.select_all_items()
        stc.simulator_config.project_manager.simulator_timeout_ms = 999999999

        for msg in stc.simulator_scene.get_selected_messages():
            msg.destination = self.dennis
            stc.ui.gvSimulator.message_updated.emit(msg)

        list_model = stc.ui.listViewSimulate.model()
        self.assertEqual(list_model.rowCount(), 2)
        list_model.setData(list_model.createIndex(1, 0), Qt.Checked, role=Qt.CheckStateRole)

        dialog = stc.get_simulator_dialog()

        network_sdr_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
        dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(network_sdr_name)

        rcv_port = self.get_free_port()
        dialog.simulator.sniffer.rcv_device.set_server_port(rcv_port)

        dialog.simulator.sniffer.adaptive_noise = False
        dialog.simulator.sniffer.automatic_center = False

        dialog.ui.btnStartStop.click()

        while not any("Waiting for message 1" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator to wait for message 1")
            time.sleep(1)

        modulator = dialog.project_manager.modulators[0]  # type: Modulator
        sender = NetworkSDRInterfacePlugin(raw_mode=True, sending=True)
        sender.client_port = rcv_port

        sender.send_raw_data(modulator.modulate("1" * 352), 1)
        time.sleep(0.5)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)

        while not any("Waiting for message 2" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for simulator wait for message 2")
            time.sleep(1)

        sender.send_raw_data(modulator.modulate("10" * 176), 1)
        time.sleep(0.5)
        sender.send_raw_data(np.zeros(1000, dtype=np.complex64), 1)
        while not any("Mismatch for label:" in msg for msg in dialog.simulator.log_messages):
            logger.debug("Waiting for mismatching message")
            time.sleep(1)

        dialog.on_timer_timeout()  # enforce writing to text view
        simulator_log = dialog.ui.textEditSimulation.toPlainText()
        self.assertIn("Received message 1", simulator_log)
        self.assertIn("preamble: 11111111", simulator_log)
        self.assertIn("Mismatch for label: preamble", simulator_log)

        dialog.close()