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 __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, is_ringbuffer=False, 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 add_signalfile(self, filename: str, group_id=0): 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 alrdy_qad_demod = False if filename.endswith(".wav"): accept, alrdy_qad_demod = WavFileDialog.dialog(self) if not accept: return 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 signal = Signal( filename, sig_name, wav_is_qad_demod=alrdy_qad_demod, sample_rate=self.project_manager.device_conf["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_audi(self): path = self.get_path("audi_auf_sr5m.coco") if not path: return data = Signal(path, "").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.assertGreaterEqual(bit_length, 2400) self.assertLessEqual(bit_length, 2500) self.assertGreaterEqual(center, 0.005) self.assertLessEqual(center, 0.32) print("noise", noise, "center", center, "bit length", bit_length, "tolerance", tolerance) demodulated = demodulate(data, mod_type, bit_length, center, noise, tolerance) print(demodulated) self.assertEqual(len(demodulated), 1) self.assertTrue(demodulated[0].startswith( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) self.assertTrue(demodulated[0].endswith("cad4c"))
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)
def test_multi_messages_different_rssi(self): data = Signal( get_path_for_data_file("multi_messages_different_rssi.coco"), "").data noise_level = detect_noise_level(np.abs(data)) self.assertGreater(noise_level, 0.001) self.assertLess(noise_level, 0.002)
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 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 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, sample_rate=sample_rate) self.file_proxy_model.open_files.add(filename) self.add_signal(signal, group_id)
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 setUp(self): self.signal = Signal(get_path_for_data_file("esaver.complex"), "test") self.signal.sample_rate = 2e6 self.dialog = SignalDetailsController(self.signal) if self.SHOW: self.dialog.show()
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.iq_array = 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_auto_detect_elektromaten(self): signal = Signal("./data/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 demodulate(signal_data, mod_type: str, bit_length, center, noise, tolerance, decoding=None, pause_threshold=8): signal = Signal("", "") if isinstance(signal_data, IQArray): signal.iq_array = signal_data else: if signal_data.dtype == np.complex64: signal.iq_array = IQArray(signal_data.view(np.float32)) else: signal.iq_array = IQArray(signal_data) signal.modulation_type = 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 __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
def test_brennenstuhl(self): path = self.get_path("brennenstuhl_signal_ABCD_onoff.coco") if not path: return data = Signal(path, "").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, 300) print("noise", noise, "center", center, "bit length", bit_length, "tolerance", tolerance) demodulated = demodulate(data, mod_type, bit_length, center, noise, tolerance, pause_threshold=8) print(demodulated) self.assertEqual(len(demodulated), 64) for i in range(64): self.assertTrue(demodulated[i].startswith("88888888888")) self.assertEqual(len(demodulated[i]), len(demodulated[0]))
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_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_ask_center_detection(self): data = Signal(get_path_for_data_file("ask.complex")).iq_array.data rect = afp_demod(data, 0.01111, "ASK", 2) center = detect_center(rect) self.assertGreaterEqual(center, 0) self.assertLessEqual(center, 0.06)
def test_fsk_15db_center_detection(self): data = Signal(get_path_for_data_file("FSK15.complex"), "").iq_array.data rect = afp_demod(data, 0, "FSK", 2) center = detect_center(rect) self.assertGreaterEqual(center, -0.1979) self.assertLessEqual(center, 0.1131)
def test_noisy_rect(self): data = Signal(get_path_for_data_file("fsk.complex")).iq_array.data rect = afp_demod(data, 0.008, "FSK", 2)[5:15000] center = detect_center(rect) self.assertGreaterEqual(center, -0.0587) self.assertLessEqual(center, 0.02)
def test_segmentation_elektromaten(self): signal = Signal(get_path_for_data_file("elektromaten.coco"), "") segments = segment_messages_from_magnitudes(signal.iq_array.magnitudes, noise_threshold=0.0167) segments = merge_message_segments_for_ook(segments) self.assertEqual(len(segments), 11)
def test_4_psk(self): bits = array.array("B", [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1]) angles_degree = [-135, -45, 45, 135] parameters = array.array("f", [np.pi*a/180 for a in angles_degree]) result = modulate_c(bits, 100, "PSK", parameters, 2, 1, 40e3, 0, 1e6, 1000, 0) signal = Signal("") signal.iq_array = IQArray(result) signal.bits_per_symbol = 2 signal.center = 0 signal.center_spacing = 1 signal.modulation_type = "PSK" proto_analyzer = ProtocolAnalyzer(signal) proto_analyzer.get_protocol_from_signal() demod_bits = proto_analyzer.plain_bits_str[0] self.assertEqual(len(demod_bits), len(bits)) self.assertTrue(demod_bits.startswith("10101010")) np.random.seed(42) noised = result + 0.1 * np.random.normal(loc=0, scale=np.sqrt(2)/2, size=(len(result), 2)) signal.iq_array = IQArray(noised.astype(np.float32)) signal.center_spacing = 1.5 signal.noise_threshold = 0.2 signal._qad = None proto_analyzer.get_protocol_from_signal() demod_bits = proto_analyzer.plain_bits_str[0] self.assertEqual(len(demod_bits), len(bits)) self.assertTrue(demod_bits.startswith("10101010"))
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 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.0387 < signal.qad_center < 0.1183) signal.bit_len = signal.estimate_bitlen() self.assertTrue(270 <= signal.bit_len <= 330)
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_noised_homematic_center_detection(self): data = Signal(get_path_for_data_file("noised_homematic.complex"), "").iq_array.data rect = afp_demod(data, 0.0, "FSK", 2) center = detect_center(rect) self.assertGreater(center, -0.0148) self.assertLess(center, 0.0024)
def test_enocean_center_detection(self): data = Signal(get_path_for_data_file("enocean.complex")).iq_array.data rect = afp_demod(data, 0.05, "ASK", 2) messages = [rect[2107:5432], rect[20428:23758], rect[44216:47546]] for i, msg in enumerate(messages): center = detect_center(msg) self.assertGreaterEqual(center, 0.04, msg=str(i)) self.assertLessEqual(center, 0.072, msg=str(i))
def setUp(self): constants.SETTINGS.setValue("NetworkSDRInterface", True) tests.utils_testing.short_wait() logger.debug("init form") self.form = MainController() self.signal = Signal(get_path_for_data_file("esaver.complex"), "testsignal") self.form.ui.tabWidget.setCurrentIndex(2)
def test_fsk(self): signal = Signal(get_path_for_data_file("fsk.complex"), "FSK-Test") signal.modulation_type = "FSK" signal.samples_per_symbol = 100 signal.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 = "ASK" signal.samples_per_symbol = 295 signal.center = 0.0219 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"))