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
def test_qad_stays_the_same(self): signal = Signal(get_path_for_data_file("esaver.complex"), "ESaver") signal.modulation_type = 1 signal.qad_center = signal.estimate_qad_center() qad_center = signal.qad_center for i in range(10): self.assertEqual(qad_center, signal.estimate_qad_center())
def test_cli_modulate_messages(self): modulator = Modulator("test") modulator.sample_rate = 2e3 modulator.samples_per_bit = 100 modulator.modulation_type_str = "ASK" modulator.param_for_zero = 0 modulator.param_for_one = 100 bits = "1010111100001" self.assertIsNone(urh_cli.modulate_messages([], modulator)) message = Message.from_plain_bits_str(bits, pause=1000) modulated = urh_cli.modulate_messages([message], modulator) # Demodulate for testing s = Signal("", "", modulation="ASK", sample_rate=2e6) s.bit_len = 100 s.noise_threshold = 0 s._fulldata = modulated pa = ProtocolAnalyzer(s) pa.get_protocol_from_signal() self.assertEqual(len(pa.messages), 1) self.assertEqual(pa.messages[0].plain_bits_str, bits)
def test_get_bit_sample_pos(self): signal = Signal(get_path_for_data_file("ASK_mod.complex"), "Bit sample pos test") signal.modulation_type = 0 signal.bit_len = 100 proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.num_messages, 1) for i, pos in enumerate(proto_analyzer.messages[0].bit_sample_pos): self.assertLess(pos, signal.num_samples, msg = i)
def test_fsk(self): signal = Signal(get_path_for_data_file("fsk.complex"), "FSK-Test") signal.modulation_type = 1 signal.bit_len = 100 signal.qad_center = 0 proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.plain_bits_str[0], "101010101010101010101010101010101100011000100110110001100010011011110100110111000001110110011000111011101111011110100100001001111001100110011100110100100011100111010011111100011")
def test_ask(self): signal = Signal(get_path_for_data_file("ask.complex"), "ASK-Test") signal.modulation_type = 0 signal.bit_len = 295 signal.qad_center = -0.1667 self.assertEqual(signal.num_samples, 13710) proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertTrue(proto_analyzer.plain_bits_str[0].startswith("1011001001011011011011011011011011001000000"))
def read_project_file_for_signal(self, signal: Signal): if self.project_file is None or len(signal.filename) == 0: return False tree = ET.parse(self.project_file) root = tree.getroot() try: signal_filename = os.path.relpath(signal.filename, self.project_path) except ValueError: signal_filename = signal.filename for sig_tag in root.iter("signal"): if sig_tag.attrib["filename"] == signal_filename: signal.name = sig_tag.attrib["name"] signal.qad_center = float(sig_tag.get("qad_center", 0)) signal.tolerance = int(sig_tag.get("tolerance", 5)) signal.noise_threshold = float(sig_tag.get("noise_threshold", 0.1)) signal.sample_rate = float(sig_tag.get("sample_rate", 1e6)) signal.bit_len = int(sig_tag.get("bit_length", 100)) signal.modulation_type = int(sig_tag.get("modulation_type", 0)) signal.pause_threshold = int(sig_tag.get("pause_threshold", 8)) signal.message_length_divisor = int(sig_tag.get("message_length_divisor", 1)) break return True
def test_fabema_get_proto(self): signal = Signal("../../noack/USRP/Fabema/Testdata/trafficlight_fhside_full.complex", "PerfTest", modulation="ASK") signal.noise_threshold = 0.1 signal.qad_center = 0.009 signal.bit_len = 16 proto_analyzer = ProtocolAnalyzer(signal) t = time.time() proto_analyzer.get_protocol_from_signal() dur = time.time() - t print(self.prefix + "Get Protocol: {0:.2f}s".format(dur)) self.assertLess(dur, 2.85)
def test_fabema_autodetect(self): total = time.time() t = time.time() signal = Signal("../../noack/USRP/Fabema/Testdata/trafficlight_fhside_full.complex", "PerfTest", modulation="ASK") # signal.noise_threshold = 0.2377 print(self.prefix + "Signal creation: {0:.2f} ({1:.2f})".format(time.time() - t, time.time() - total)) t = time.time() signal.qad_center = signal.estimate_qad_center() print(self.prefix + "Quad Center Estimation: {0:.2f} ({1:.2f})".format(time.time() - t, time.time() - total)) t = time.time() signal.bit_len = signal.estimate_bitlen() print(self.prefix + "Bit Len Estimation: {0:.2f} ({1:.2f})".format(time.time() - t, time.time() - total))
def test_get_rssi_of_message(self): signal = Signal(get_path_for_data_file("two_participants.coco"), "RSSI-Test") signal.modulation_type = 1 signal.bit_len = 100 signal.qad_center = -0.0507 proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.num_messages, 18) messages = proto_analyzer.messages self.assertLess(messages[0].rssi, messages[1].rssi) self.assertGreater(messages[1].rssi, messages[2].rssi) self.assertLess(messages[2].rssi, messages[3].rssi) self.assertLess(messages[-2].rssi, messages[-1].rssi)
def __init__(self, project_manager, modulated_data, parent=None, testing_mode=False): super().__init__(project_manager, is_tx=True, parent=parent, testing_mode=testing_mode) self.graphics_view = self.ui.graphicsViewSend self.ui.stackedWidget.setCurrentWidget(self.ui.page_send) self.hide_receive_ui_items() self.ui.btnStart.setIcon(QIcon.fromTheme("media-playback-start")) self.setWindowTitle("Send Signal") self.setWindowIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStart.setToolTip("Send data") self.ui.btnStop.setToolTip("Stop sending") self.device_is_sending = False if modulated_data is not None: # modulated_data is none in continuous send mode self.ui.progressBar.setMaximum(len(modulated_data)) samp_rate = self.ui.spinBoxSampleRate.value() signal = Signal.from_samples(modulated_data, "Modulated Preview", samp_rate) self.scene_manager = SignalSceneManager(signal, parent=self) self.send_indicator = self.scene_manager.scene.addRect(0, -2, 0, 4, QPen(QColor(Qt.transparent), Qt.FlatCap), QBrush(constants.SEND_INDICATOR_COLOR)) self.send_indicator.stackBefore(self.scene_manager.scene.selection_area) self.scene_manager.init_scene() self.graphics_view.set_signal(signal) self.graphics_view.sample_rate = samp_rate self.init_device() self.graphics_view.setScene(self.scene_manager.scene) self.graphics_view.scene_manager = self.scene_manager self.create_connects()
def test_write(self): signal = Signal(get_path_for_data_file("ask.complex"), "ASK-Test") signal.modulation_type = 0 signal.bit_len = 295 signal.qad_center = -0.1667 self.assertEqual(signal.num_samples, 13710) proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.decoded_hex_str[0], "b25b6db6c80") proto_analyzer.messages.append(copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append(copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append(copy.deepcopy(proto_analyzer.messages[0])) pcap = PCAP() pcap.write_packets(proto_analyzer.messages, os.path.join(tempfile.gettempdir(), "test.pcap"), 1e6)
def test_freq_detection(self): s = Signal(get_path_for_data_file("steckdose_anlernen.complex"), "RWE") s.noise_threshold = 0.06 s.qad_center = 0 s.bit_len = 100 pa = ProtocolAnalyzer(s) pa.get_protocol_from_signal() self.assertEqual(pa.messages[0].plain_bits_str, "101010101010101010101010101010101001101001111101100110100111110111010010011000010110110101111" "010111011011000011000101000010001001101100101111010110100110011100100110000101001110100001111" "111101000111001110000101110100100111010110110100001101101101010100011011010001010110011100011" "010100010101111110011010011001000000110010011010001000100100100111101110110010011111011100010" "10110010100011111101110111000010111100111101001011101101011011010110101011100") start, nsamples = pa.get_samplepos_of_bitseq(0, 0, 0, 1, False) freq = s.estimate_frequency(start, start + nsamples, 1e6) self.assertEqual(freq, 10000) # Freq for 1 is 10K
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, device: str, backend_handler: BackendHandler, network_raw_mode=False): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.network_raw_mode = network_raw_mode self.backend_handler = backend_handler self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, resume_on_full_receive_buffer=True, raw_mode=network_raw_mode) self.sniff_thread = Thread(target=self.check_for_data, daemon=True) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.__buffer = np.zeros(int(self.BUFFER_SIZE_MB * 1000 * 1000 / 8), dtype=np.complex64) self.__current_buffer_index = 0 self.reading_data = False self.adaptive_noise = False self.automatic_center = False self.pause_length = 0 self.is_running = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, device: str, backend_handler: BackendHandler): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.backend_handler = backend_handler self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, resume_on_full_receive_buffer=True, raw_mode=False) self.rcv_device.index_changed.connect(self.on_rcv_thread_index_changed) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.data_cache = [] self.conseq_non_data = 0 self.reading_data = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def test_fsk_freq_detection(self): s = Signal(get_path_for_data_file("steckdose_anlernen.complex"), "RWE") s.noise_threshold = 0.06 s.qad_center = 0 s.bit_len = 100 pa = ProtocolAnalyzer(s) pa.get_protocol_from_signal() self.assertEqual(pa.messages[0].plain_bits_str, "101010101010101010101010101010101001101001111101100110100111110111010010011000010110110101111" "010111011011000011000101000010001001101100101111010110100110011100100110000101001110100001111" "111101000111001110000101110100100111010110110100001101101101010100011011010001010110011100011" "010100010101111110011010011001000000110010011010001000100100100111101110110010011111011100010" "10110010100011111101110111000010111100111101001011101101011011010110101011100") freq = pa.estimate_frequency_for_one(1e6) self.assertAlmostEqual(1, freq / 10000, places = 1) # Freq for 1 is 10K freq = pa.estimate_frequency_for_zero(1e6) self.assertAlmostEqual(3, freq / 10000, places = 1) # Freq for 0 is 30K
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)
def test_fsk_live_capture(self): data = Signal(get_path_for_data_file("fsk_live.coco"), "").iq_array.data n = 10 moving_average_filter = Filter([1 / n for _ in range(n)], filter_type=FilterType.moving_average) filtered_data = moving_average_filter.apply_fir_filter( data.flatten()).view(np.float32) filtered_data = filtered_data.reshape((len(filtered_data) // 2, 2)) rect = afp_demod(filtered_data, 0.0175, "FSK") center = detect_center(rect) self.assertGreaterEqual(center, -0.0148, msg="Filtered") self.assertLessEqual(center, 0.01, msg="Filtered") rect = afp_demod(data, 0.0175, "FSK") center = detect_center(rect) self.assertGreaterEqual(center, -0.02, msg="Original") self.assertLessEqual(center, 0.01, msg="Original")
def test_write(self): signal = Signal(get_path_for_data_file("ask.complex"), "ASK-Test") signal.modulation_type = 0 signal.bit_len = 295 signal.qad_center = -0.1667 self.assertEqual(signal.num_samples, 13710) proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.decoded_hex_str[0], "b25b6db6c80") proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) pcap = PCAP() pcap.write_packets(proto_analyzer.messages, "/tmp/test.pcap", 1e6)
def test_fsk_freq_detection(self): s = Signal(get_path_for_data_file("steckdose_anlernen.complex"), "RWE") s.noise_threshold = 0.06 s.qad_center = 0 s.bit_len = 100 pa = ProtocolAnalyzer(s) pa.get_protocol_from_signal() self.assertEqual( pa.messages[0].plain_bits_str, "101010101010101010101010101010101001101001111101100110100111110111010010011000010110110101111" "010111011011000011000101000010001001101100101111010110100110011100100110000101001110100001111" "111101000111001110000101110100100111010110110100001101101101010100011011010001010110011100011" "010100010101111110011010011001000000110010011010001000100100100111101110110010011111011100010" "10110010100011111101110111000010111100111101001011101101011011010110101011100" ) freq = pa.estimate_frequency_for_one(1e6) self.assertAlmostEqual(1, freq / 10000, places=1) # Freq for 1 is 10K freq = pa.estimate_frequency_for_zero(1e6) self.assertAlmostEqual(3, freq / 10000, places=1) # Freq for 0 is 30K
def __init__(self, project_manager, modulated_data, modulation_msg_indices=None, parent=None, testing_mode=False): super().__init__(project_manager, is_tx=True, parent=parent, testing_mode=testing_mode) self.graphics_view = self.ui.graphicsViewSend self.ui.stackedWidget.setCurrentWidget(self.ui.page_send) self.hide_receive_ui_items() self.ui.btnStart.setIcon(QIcon.fromTheme("media-playback-start")) self.setWindowTitle("Send Signal") self.setWindowIcon(QIcon.fromTheme("media-playback-start")) self.ui.btnStart.setToolTip("Send data") self.ui.btnStop.setToolTip("Stop sending") self.device_is_sending = False self.modulation_msg_indices = modulation_msg_indices if self.modulation_msg_indices is not None: self.ui.progressBarMessage.setMaximum( len(self.modulation_msg_indices)) else: self.ui.progressBarMessage.hide() self.ui.labelCurrentMessage.hide() if modulated_data is not None: # modulated_data is none in continuous send mode self.ui.progressBarSample.setMaximum(len(modulated_data)) samp_rate = self.device_settings_widget.ui.spinBoxSampleRate.value( ) signal = Signal.from_samples(modulated_data, "Modulated Preview", samp_rate) self.scene_manager = SignalSceneManager(signal, parent=self) self.send_indicator = self.scene_manager.scene.addRect( 0, -2, 0, 4, QPen(QColor(Qt.transparent), Qt.FlatCap), QBrush(constants.SEND_INDICATOR_COLOR)) self.send_indicator.stackBefore( self.scene_manager.scene.selection_area) self.scene_manager.init_scene() self.graphics_view.set_signal(signal) self.graphics_view.sample_rate = samp_rate self.init_device() self.graphics_view.setScene(self.scene_manager.scene) self.graphics_view.scene_manager = self.scene_manager self.create_connects()
def test_auto_detect_ask(self): signal = Signal(get_path_for_data_file("ask.complex"), "ASK") signal.modulation_type = 0 signal.qad_center = signal.estimate_qad_center() self.assertTrue(0 <= signal.qad_center <= 0.0036) signal.bit_len = signal.estimate_bitlen() self.assertTrue(270 <= signal.bit_len <= 330)
def test_auto_detect_esaver(self): signal = Signal(get_path_for_data_file("esaver.complex"), "ESaver") signal.modulation_type = 1 signal.qad_center = signal.estimate_qad_center() self.assertTrue(0.24 < signal.qad_center < 0.5) signal.bit_len = signal.estimate_bitlen() self.assertTrue(80 <= signal.bit_len <= 120)
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, sample_rate: float, freq: float, gain: int, bandwidth: float, device: str, usrp_ip="192.168.10.2"): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.backend_handler = BackendHandler() self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, bandwidth, freq, gain, sample_rate, device_ip=usrp_ip, is_ringbuffer=True) self.rcv_device.index_changed.connect(self.on_rcv_thread_index_changed) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.rcv_timer = QTimer() self.rcv_timer.setInterval(1000) self.rcv_timer.timeout.connect(self.on_rcv_timer_timeout) self.rel_symbol_len = self._read_symbol_len() self.data_cache = [] self.conseq_non_data = 0 self.reading_data = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def test_auto_detect_fsk(self): signal = Signal(get_path_for_data_file("fsk.complex"), "FSK") signal.modulation_type = 1 signal.qad_center = signal.estimate_qad_center() self.assertTrue(-0.1 <= signal.qad_center <= 0) signal.bit_len = signal.estimate_bitlen() self.assertTrue(90 <= signal.bit_len <= 110)
def test_auto_detect_elektromaten(self): signal = Signal(get_path_for_data_file("elektromaten.complex"), "Elektromaten") signal.modulation_type = 0 signal.qad_center = signal.estimate_qad_center() self.assertTrue(0.0015 < signal.qad_center < 0.0140) signal.bit_len = signal.estimate_bitlen() self.assertTrue(270 <= signal.bit_len <= 330)
def add_signalfile(self, filename: str, group_id=0, enforce_sample_rate=None): if not os.path.exists(filename): QMessageBox.critical( self, self.tr("File not Found"), self.tr( "The file {0} could not be found. Was it moved or renamed?" ).format(filename)) return already_qad_demodulated = False if filename.endswith(".wav"): cb = QCheckBox("Signal in file is already quadrature demodulated") msg = self.tr( "You selected a .wav file as signal.\n" "Universal Radio Hacker (URH) will interpret it as real part of the signal.\n" "Protocol results may be bad due to missing imaginary part.\n\n" "Load a complex file if you experience problems.\n" "You have been warned.") msg_box = QMessageBox(QMessageBox.Information, "WAV file selected", msg) msg_box.addButton(QMessageBox.Ok) msg_box.addButton(QMessageBox.Abort) msg_box.setCheckBox(cb) reply = msg_box.exec() if reply != QMessageBox.Ok: return already_qad_demodulated = cb.isChecked() sig_name = os.path.splitext(os.path.basename(filename))[0] # Use default sample rate for signal # Sample rate will be overriden in case of a project later if enforce_sample_rate is not None: sample_rate = enforce_sample_rate else: sample_rate = self.project_manager.device_conf["sample_rate"] signal = Signal(filename, sig_name, wav_is_qad_demod=already_qad_demodulated, sample_rate=sample_rate) if self.project_manager.project_file is None: self.adjust_for_current_file(signal.filename) self.file_proxy_model.open_files.add(filename) self.add_signal(signal, group_id)
def test_ask_50_center_detection(self): message_indices = [(0, 8000), (18000, 26000), (36000, 44000), (54000, 62000), (72000, 80000)] data = Signal(get_path_for_data_file("ask50.complex")).iq_array.data rect = afp_demod(data, 0.0509, "ASK", 2) for start, end in message_indices: center = detect_center(rect[start:end]) self.assertGreaterEqual(center, 0.4, msg="{}/{}".format(start, end)) self.assertLessEqual(center, 0.65, msg="{}/{}".format(start, end))
def test_psk(self): signal = Signal(get_path_for_data_file("psk_gen_noisy.complex"), "PSK-Test") signal.modulation_type = "PSK" signal.samples_per_symbol = 300 signal.center = 0 signal.noise_threshold = 0 signal.tolerance = 10 proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertTrue(proto_analyzer.plain_bits_str[0].startswith("1011"), msg=proto_analyzer.plain_bits_str[0])
def test_fabema_many_messages(self): signal = Signal("../../noack/USRP/Fabema/Testdata/trafficlight_fhside_full.complex", "PerfTest", modulation="ASK") signal.noise_threshold = 0.1 signal.qad_center = -0.0249 signal.bit_len = 1 proto_analyzer = ProtocolAnalyzer(signal) t = time.time() proto_analyzer.get_protocol_from_signal() print("Got protocol", time.time() - t) t = time.time() proto_analyzer.plain_to_string(0) total = time.time() - t print("First run", total) t = time.time() proto_analyzer.plain_to_string(0) total = time.time() - t print("With cached", total) print("Num Messages", proto_analyzer.num_messages)
def test_write_pcap(self): signal = Signal(get_path_for_data_file("ask.complex"), "ASK-Test") signal.modulation_type = "ASK" signal.samples_per_symbol = 295 signal.center = -0.1667 self.assertEqual(signal.num_samples, 13710) proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.decoded_hex_str[0], "b25b6db6c80") proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) proto_analyzer.messages.append( copy.deepcopy(proto_analyzer.messages[0])) pcap = PCAP() pcap.write_packets(proto_analyzer.messages, os.path.join(tempfile.gettempdir(), "test.pcap"), 1e6)
def test_message_segmentation_fsk_xavax(self): signal = Signal(get_path_for_data_file("xavax.coco"), "") segments = segment_messages_from_magnitudes(signal.iq_array.magnitudes, noise_threshold=0.002) # Signal starts with overdrive, so one message more self.assertTrue(len(segments) == 6 or len(segments) == 7) if len(segments) == 7: segments = segments[1:] self.assertEqual(segments, [(275146, 293697), (321073, 338819), (618213, 1631898), (1657890, 1678041), (1803145, 1820892), (1846213, 1866364)])
def test_auto_interpretation_xavax(self): signal = Signal(get_path_for_data_file("xavax.coco"), "") result = AutoInterpretation.estimate(signal.iq_array.data) mod_type, bit_length = result["modulation_type"], result["bit_length"] center, noise, tolerance = result["center"], result["noise"], result["tolerance"] self.assertEqual(mod_type, "FSK") self.assertEqual(bit_length, 100) demod = demodulate(signal.iq_array.data, mod_type, bit_length, center, noise, tolerance) self.assertGreaterEqual(len(demod), 5) for i in range(1, len(demod)): self.assertTrue(demod[i].startswith("aaaaaaaa"))
def test_psk(self): signal = Signal(get_path_for_data_file("psk_gen_noisy.complex"), "PSK-Test") signal.modulation_type = 2 signal.bit_len = 300 signal.qad_center = 0.0281 signal.noise_threshold = 0 signal.tolerance = 10 proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.plain_bits_str[0], "101100")
def demodulate(signal_data, mod_type: str, bit_length, center, noise, tolerance, decoding=None, pause_threshold=8): signal = Signal("", "") signal._fulldata = signal_data signal.modulation_type = signal.MODULATION_TYPES.index(mod_type) signal.bit_len = bit_length signal.qad_center = center signal.noise_threshold = noise signal.pause_threshold = pause_threshold if tolerance is not None: signal.tolerance = tolerance pa = ProtocolAnalyzer(signal) if decoding is not None: pa.decoder = decoding pa.get_protocol_from_signal() return pa.decoded_hex_str
def test_carrier_auto_detect(self): signal = Signal(get_path_for_data_file("wsp.complex"), "test") signal.modulation_type = "ASK" signal.noise_threshold = 0.035 signal.center = 0.0245 signal.samples_per_symbol = 25 pa = ProtocolAnalyzer(signal) pa.get_protocol_from_signal() start, num_samples = pa.get_samplepos_of_bitseq(0, 0, 0, 999999, include_pause=False) print("-----------") print(signal.estimate_frequency(start, end=start+num_samples, sample_rate=2e6))
def test_ask_two(self): signal = Signal(get_path_for_data_file("ask_short.complex"), "ASK-Test2") signal.modulation_type = "ASK" signal.noise_threshold = 0.0299 signal.samples_per_symbol = 16 signal.center = 0.1300 signal.tolerance = 0 self.assertEqual(signal.num_samples, 131) proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() self.assertEqual(proto_analyzer.plain_bits_str[0], "10101010")
def test_auto_interpretation_elektromaten(self): data = Signal(get_path_for_data_file("elektromaten.complex16s"), "").iq_array result = AutoInterpretation.estimate(data) mod_type, bit_length = result["modulation_type"], result["bit_length"] center, noise, tolerance = result["center"], result["noise"], result["tolerance"] self.assertEqual(mod_type, "ASK") self.assertEqual(bit_length, 600) demodulated = demodulate(data, mod_type, bit_length, center, noise, tolerance, pause_threshold=8) self.assertEqual(len(demodulated), 11) for i in range(11): self.assertTrue(demodulated[i].startswith("8"))
def test_homematic_center_detection(self): data = Signal(get_path_for_data_file("homematic.coco"), "").data rect = afp_demod(data, 0.0012, 1) msg1 = rect[17719:37861] msg2 = rect[70412:99385] center1 = detect_center(msg1) self.assertGreaterEqual(center1, -0.1285) self.assertLessEqual(center1, -0.0413) center2 = detect_center(msg2) self.assertGreaterEqual(center2, -0.1377) self.assertLessEqual(center2, -0.0367)
def test_auto_interpretation_homematic(self): data = Signal(get_path_for_data_file("homematic.complex32s"), "").iq_array result = AutoInterpretation.estimate(data) mod_type, bit_length = result["modulation_type"], result["bit_length"] center, noise, tolerance = result["center"], result["noise"], result["tolerance"] self.assertEqual(mod_type, "FSK") self.assertEqual(bit_length, 100) demodulated = demodulate(data, mod_type, bit_length, center, noise, tolerance) self.assertEqual(len(demodulated), 2) for i in range(2): self.assertTrue(demodulated[i].startswith("aaaaaaaa"))
def __init__(self, freq, samp_rate, bw, gain, device: str, modulated_data, parent=None, testing_mode=False): self.is_tx = True super().__init__(freq, samp_rate, bw, gain, device, parent=parent, testing_mode=testing_mode) self.update_interval = 25 self.graphics_view = self.ui.graphicsViewSend self.ui.stackedWidget.setCurrentIndex(1) self.hide_receive_ui_items() self.ui.btnStart.setIcon(QIcon.fromTheme("media-playback-start")) self.setWindowTitle("Send signal") self.ui.btnStart.setToolTip("Send data") self.ui.btnStop.setToolTip("Stop sending") self.ui.progressBar.setMaximum(len(modulated_data)) self.device_is_sending = False signal = Signal.from_samples(modulated_data, "Modulated Preview", samp_rate) self.scene_manager = SignalSceneManager(signal, parent=self) self.send_indicator = self.scene_manager.scene.addRect( 0, -2, 0, 4, QPen(QColor(Qt.transparent), Qt.FlatCap), QBrush(constants.SEND_INDICATOR_COLOR)) self.send_indicator.stackBefore( self.scene_manager.scene.selection_area) self.scene_manager.init_scene() self.graphics_view.set_signal(signal) self.graphics_view.sample_rate = samp_rate self.init_device() self.graphics_view.setScene(self.scene_manager.scene) self.graphics_view.scene_manager = self.scene_manager self.create_connects()
def read_project_file_for_signal(self, signal: Signal): if self.project_file is None or len(signal.filename) == 0: return False tree = ET.parse(self.project_file) root = tree.getroot() try: signal_filename = os.path.relpath(signal.filename, self.project_path) except ValueError: signal_filename = signal.filename for sig_tag in root.iter("signal"): if sig_tag.attrib["filename"] == signal_filename: signal.name = sig_tag.attrib["name"] signal.qad_center = float(sig_tag.get("qad_center", 0)) signal.tolerance = int(sig_tag.get("tolerance", 5)) signal.noise_threshold = float( sig_tag.get("noise_threshold", 0.1)) signal.sample_rate = float(sig_tag.get("sample_rate", 1e6)) signal.bit_len = int(sig_tag.get("bit_length", 100)) try: # Legacy support when modulation type was integer signal.modulation_type = Signal.MODULATION_TYPES[int( sig_tag.get("modulation_type", 0))] except (ValueError, IndexError): signal.modulation_type = sig_tag.get( "modulation_type", "ASK") signal.pause_threshold = int(sig_tag.get("pause_threshold", 8)) signal.message_length_divisor = int( sig_tag.get("message_length_divisor", 1)) break return True
def __demodulate(self, connection: socket.socket): connection.settimeout(0.5) 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
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, sample_rate: float, freq: float, gain: int, bandwidth: float, device: str, usrp_ip="192.168.10.2"): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_treshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) super().__init__(signal) self.rcv_thrd = ReceiverThread(sample_rate, freq, gain, bandwidth, initial_bufsize=1e8, is_ringbuffer=True) self.rcv_thrd.usrp_ip = usrp_ip self.rcv_thrd.device = device self.rcv_thrd.index_changed.connect(self.on_rcv_thread_index_changed) self.rcv_timer = QTimer() self.rcv_timer.setInterval(1000) self.rcv_timer.timeout.connect(self.on_rcv_timer_timeout) self.rel_symbol_len = self._read_symbol_len() self.data_cache = [] self.conseq_non_data = 0 self.reading_data = False self.store_blocks = True self.__sniff_file = "" self.__store_data = True
def read_project_file_for_signal(self, signal: Signal): if self.project_file is None or len(signal.filename) == 0: return False tree = ET.parse(self.project_file) root = tree.getroot() for sig_tag in root.iter("signal"): if sig_tag.attrib["filename"] == os.path.relpath(signal.filename, self.project_path): signal.name = sig_tag.attrib["name"] signal.qad_center = float(sig_tag.get("qad_center", 0)) signal.tolerance = int(sig_tag.get("tolerance", 5)) signal.noise_threshold = float(sig_tag.get("noise_threshold", 0.1)) signal.sample_rate = float(sig_tag.get("sample_rate", 1e6)) signal.bit_len = int(sig_tag.get("bit_length", 100)) signal.modulation_type = int(sig_tag.get("modulation_type", 0)) signal.pause_threshold = int(sig_tag.get("pause_threshold", 8)) signal.message_length_divisor = int(sig_tag.get("message_length_divisor", 1)) break return True
def test_fsk_live_capture(self): data = Signal(get_path_for_data_file("fsk_live.coco"), "").data n = 10 moving_average_filter = Filter([1 / n for _ in range(n)], filter_type=FilterType.moving_average) filtered_data = moving_average_filter.apply_fir_filter(data) rect = afp_demod(filtered_data, 0.0175, 1) center = detect_center(rect) self.assertGreaterEqual(center, -0.0148, msg="Filtered") self.assertLessEqual(center, 0.01, msg="Filtered") rect = afp_demod(data, 0.0175, 1) center = detect_center(rect) self.assertGreaterEqual(center, -0.02, msg="Original") self.assertLessEqual(center, 0.01, msg="Original")
def test_auto_interpretation_elektromaten(self): data = Signal(get_path_for_data_file("elektromaten.coco"), "").data result = AutoInterpretation.estimate(data) mod_type, bit_length = result["modulation_type"], result["bit_length"] center, noise, tolerance = result["center"], result["noise"], result[ "tolerance"] self.assertEqual(mod_type, "ASK") self.assertEqual(bit_length, 600) demodulated = demodulate(data, mod_type, bit_length, center, noise, tolerance, pause_threshold=8) self.assertEqual(len(demodulated), 11) for i in range(11): self.assertTrue(demodulated[i].startswith("8")) # Test with added 20% noise np.random.seed(5) noise = np.random.normal(loc=0, scale=1, size=2 * len(data)).astype( np.float32).view(np.complex64) noised_data = data + 0.2 * np.mean(np.abs(data)) * noise result = AutoInterpretation.estimate(noised_data) mod_type, bit_length = result["modulation_type"], result["bit_length"] center, noise, tolerance = result["center"], result["noise"], result[ "tolerance"] self.assertEqual(mod_type, "ASK") self.assertEqual(bit_length, 600) demodulated = demodulate(noised_data, mod_type, bit_length, center, noise, tolerance, pause_threshold=8) self.assertEqual(len(demodulated), 11) for i in range(11): self.assertTrue(demodulated[i].startswith("8"))
def test_carrier_auto_detect(self): signal = Signal(get_path_for_data_file("wsp.complex"), "test") signal.modulation_type = 0 signal.noise_threshold = 0.035 signal.qad_center = 0.0245 signal.bit_len = 25 pa = ProtocolAnalyzer(signal) pa.get_protocol_from_signal() start, num_samples = pa.get_samplepos_of_bitseq(0, 0, 0, 999999, include_pause=False) print("-----------") print(signal.estimate_frequency(start, end=start+num_samples, sample_rate=2e6))
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, device: str, backend_handler: BackendHandler, network_raw_mode=False): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.network_raw_mode = network_raw_mode self.backend_handler = backend_handler self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, resume_on_full_receive_buffer=True, raw_mode=network_raw_mode) signal.iq_array = IQArray(None, self.rcv_device.data_type, 0) self.sniff_thread = Thread(target=self.check_for_data, daemon=True) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.__buffer = IQArray(None, np.float32, 0) self.__init_buffer() self.__current_buffer_index = 0 self.reading_data = False self.adaptive_noise = False self.automatic_center = False self.pause_length = 0 self.is_running = False self.store_messages = True self.__sniff_file = "" self.__store_data = True
def __init__(self, bit_len: int, center: float, noise: float, tolerance: int, modulation_type: int, device: str, backend_handler: BackendHandler, network_raw_mode=False): signal = Signal("", "LiveSignal") signal.bit_len = bit_len signal.qad_center = center signal.noise_threshold = noise signal.tolerance = tolerance signal.silent_set_modulation_type(modulation_type) ProtocolAnalyzer.__init__(self, signal) QObject.__init__(self, None) self.network_raw_mode = network_raw_mode self.backend_handler = backend_handler self.rcv_device = VirtualDevice(self.backend_handler, device, Mode.receive, resume_on_full_receive_buffer=True, raw_mode=network_raw_mode) self.rcv_device.emit_data_received_signal = True self.rcv_device.data_received.connect(self.on_data_received) self.rcv_device.started.connect(self.__emit_started) self.rcv_device.stopped.connect(self.__emit_stopped) self.real_time = real_time self.data_cache = [] self.reading_data = False self.adaptive_noise = False self.pause_length = 0 self.store_messages = True self.__sniff_file = "" self.__store_data = True
def test_gfsk(self): modulator = Modulator("gfsk") modulator.modulation_type_str = "FSK" modulator.samples_per_bit = 100 modulator.sample_rate = 1e6 modulator.param_for_one = 20e3 modulator.param_for_zero = -10e3 modulator.modulate([True, False, False, True, False], 9437) s = modulator.modulated_samples modulator.modulate([True, False, True], 9845) #, start=len(s)) s = np.concatenate((s, modulator.modulated_samples)) modulator.modulate([True, False, True, False], 8457) #, start=len(s)) s = np.concatenate((s, modulator.modulated_samples)) s.tofile("/tmp/test.complex") pa = ProtocolAnalyzer(Signal("/tmp/test.complex", "test", modulation="FSK")) pa.get_protocol_from_signal()
def read_project_file_for_signal(self, signal: Signal): if self.project_file is None or len(signal.filename) == 0: return False tree = ET.parse(self.project_file) root = tree.getroot() for sig_tag in root.iter("signal"): if sig_tag.attrib["filename"] == os.path.relpath(signal.filename, self.project_path): signal.name = sig_tag.attrib["name"] signal.qad_center = float(sig_tag.get("qad_center", 0)) signal.tolerance = int(sig_tag.get("tolerance", 5)) signal.auto_detect_on_modulation_changed = False if \ sig_tag.attrib[ "auto_detect_on_modulation_changed"] == 'False' else True signal.noise_threshold = float(sig_tag.get("noise_threshold", 0.1)) signal.sample_rate = float(sig_tag.get("sample_rate", 1e6)) signal.bit_len = int(sig_tag.get("bit_length", 100)) signal.modulation_type = int(sig_tag.get("modulation_type", 0)) break return True
def test_ask_fsk_psk_modulation(self): modulations = ["ASK", "FSK", "PSK"] for i, modulation in enumerate(modulations): modulator = Modulator(modulation) tmp_dir = QDir.tempPath() filename = "{0}_mod.complex".format(modulation) filename = os.path.join(tmp_dir, filename) modulator.modulation_type = i modulator.samples_per_bit = self.samples_per_bit if modulation == "ASK": modulator.param_for_zero = 0 modulator.param_for_one = 100 elif modulation == "FSK": modulator.param_for_zero = 1000 modulator.param_for_one = 2500 elif modulation == "PSK": modulator.param_for_zero = 0 modulator.param_for_one = 180 modulator.modulate(self.modulation_data, self.pause) modulator.modulated_samples.tofile(filename) signal = Signal(filename, modulation) signal.modulation_type = i signal.bit_len = self.samples_per_bit if modulation == "ASK": signal.qad_center = 0.5 elif modulation == "FSK": signal.qad_center = 0.0097 elif modulation == "PSK": signal.qad_center = 0 self.assertEqual(signal.num_samples, self.total_samples, msg=modulation) pa = ProtocolAnalyzer(signal) pa.get_protocol_from_signal() self.assertEqual(1, len(pa.messages), msg=modulation) self.assertEqual(self.modulation_data, pa.messages[0].plain_bits, msg=modulation)