def device_send(cls, ctrl_connection: Connection, send_config: SendConfig, dev_parameters: OrderedDict): if not cls.init_device(ctrl_connection, is_tx=True, parameters=dev_parameters): return False if cls.ASYNCHRONOUS: cls.enter_async_send_mode(send_config.get_data_to_send) else: cls.prepare_sync_send(ctrl_connection) exit_requested = False buffer_size = cls.CONTINUOUS_SEND_BUFFER_SIZE if send_config.continuous else cls.SEND_BUFFER_SIZE if not cls.ASYNCHRONOUS and buffer_size == 0: logger.warning("Send buffer size is zero!") while not exit_requested and not send_config.sending_is_finished(): if cls.ASYNCHRONOUS: time.sleep(0.5) else: cls.send_sync(send_config.get_data_to_send(buffer_size)) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=True) if result == cls.Command.STOP.name: exit_requested = True break if exit_requested: logger.debug("{}: exit requested. Stopping sending".format(cls.__class__.__name__)) if send_config.sending_is_finished(): logger.debug("{}: sending is finished.".format(cls.__class__.__name__)) cls.shutdown_device(ctrl_connection) ctrl_connection.close()
def on_line_edit_parameters_editing_finished(self): if not self.ui.lineEditParameters.hasAcceptableInput(): return text = self.ui.lineEditParameters.text() parameters = [] for param in text.split("/"): param = param.upper().replace(",", ".") factor = 1 if param.endswith("G"): factor = 10**9 param = param[:-1] elif param.endswith("M"): factor = 10**6 param = param[:-1] elif param.endswith("K"): factor = 10**3 param = param[:-1] try: parameters.append(factor * float(param)) except ValueError: logger.warning("Could not convert {} to number".format(param)) return self.current_modulator.parameters[:] = array("f", parameters) self.draw_modulated() self.show_full_scene()
def __ensure_message_length_multiple(bit_data, bit_len: int, pauses, bit_sample_pos, divisor: int): """ In case of ASK modulation, this method tries to use pauses after messages as zero bits so that the bit lengths of messages are divisible by divisor :param bit_data: List of bit arrays :param bit_len: Bit length that was used for demodulation :param pauses: List of pauses :param bit_sample_pos: List of Array of bit sample positions :param divisor: Divisor the messages should be divisible by """ for i in range(len(bit_data)): missing_bits = (divisor - (len(bit_data[i]) % divisor)) % divisor if missing_bits > 0 and pauses[i] >= bit_len * missing_bits: bit_data[i].extend([0] * missing_bits) pauses[i] = pauses[i] - missing_bits * bit_len try: bit_sample_pos[i][-1] = bit_sample_pos[i][-2] + bit_len except IndexError as e: logger.warning("Error padding message " + str(e)) continue bit_sample_pos[i].extend([ bit_sample_pos[i][-1] + (k + 1) * bit_len for k in range(missing_bits - 1) ]) bit_sample_pos[i].append(bit_sample_pos[i][-1] + pauses[i])
def str2val(str_val, dtype, default=0): try: return dtype(str_val) except (ValueError, TypeError): logger.warning("The {0} is not a valid {1}, assuming {2}".format( str_val, str(dtype), str(default))) return default
def stop_tx_mode(self, msg): try: self.parent_ctrl_conn.send(self.Command.STOP.name) except (BrokenPipeError, OSError) as e: logger.debug("Closing parent control connection: " + str(e)) logger.info("{0}: Stopping TX Mode: {1}".format(self.__class__.__name__, msg)) if hasattr(self, "transmit_process") and self.transmit_process.is_alive(): self.transmit_process.join(self.JOIN_TIMEOUT) if self.transmit_process.is_alive(): logger.warning("{0}: Transmit process is still alive, terminating it".format(self.__class__.__name__)) self.transmit_process.terminate() self.transmit_process.join() self.is_transmitting = False try: self.parent_ctrl_conn.close() except OSError as e: logger.exception(e) try: self.child_ctrl_conn.close() except OSError as e: logger.exception(e)
def to_xml(self, decoders=None, include_message_type=False, write_bits=False) -> ET.Element: root = ET.Element("message") root.set("message_type_id", self.message_type.id) root.set("modulator_index", str(self.modulator_index)) root.set("pause", str(self.pause)) root.set("timestamp", str(self.timestamp)) if write_bits: root.set("bits", self.plain_bits_str) if decoders: try: decoding_index = decoders.index(self.decoder) except ValueError: logger.warning( "Failed to find '{}' in list of decodings".format( self.decoder.name)) decoding_index = 0 root.set("decoding_index", str(decoding_index)) if self.participant is not None: root.set("participant_id", self.participant.id) if include_message_type: root.append(self.message_type.to_xml()) return root
def set_device_bandwidth(self, bandwidth): if hasattr(rtlsdr, "set_tuner_bandwidth"): super().set_device_bandwidth(bandwidth) else: logger.warning( "Setting the bandwidth is not supported by your RTL-SDR driver version." )
def stop_tx_mode(self, msg): try: self.parent_ctrl_conn.send(self.Command.STOP.name) except (BrokenPipeError, OSError) as e: logger.debug("Closing parent control connection: " + str(e)) logger.info("{0}: Stopping TX Mode: {1}".format( self.__class__.__name__, msg)) if hasattr(self, "transmit_process") and self.transmit_process.is_alive(): self.transmit_process.join(self.JOIN_TIMEOUT) if self.transmit_process.is_alive(): logger.warning( "{0}: Transmit process is still alive, terminating it". format(self.__class__.__name__)) self.transmit_process.terminate() self.transmit_process.join() self.is_transmitting = False try: self.parent_ctrl_conn.close() except OSError as e: logger.exception(e) try: self.child_ctrl_conn.close() except OSError as e: logger.exception(e)
def process_command(cls, command, ctrl_connection, is_tx: bool): is_rx = not is_tx if command == cls.Command.STOP.name: return cls.Command.STOP.name tag, value = command try: if isinstance(cls.DEVICE_METHODS[tag], str): method_name = cls.DEVICE_METHODS[tag] elif isinstance(cls.DEVICE_METHODS[tag], dict): method_name = cls.DEVICE_METHODS[tag]["rx" if is_rx else "tx"] else: method_name = None except KeyError: method_name = None if method_name: try: try: check_method_name = cls.DEVICE_METHODS[tag+"_get_allowed_values"] allowed_values = getattr(cls.DEVICE_LIB, check_method_name)() next_allowed = min(allowed_values, key=lambda x: abs(x-value)) if value != next_allowed: ctrl_connection.send("{}: {} not in range of supported values. Assuming {}".format( tag, value, next_allowed )) value = next_allowed except (KeyError, AttributeError): pass ret = getattr(cls.DEVICE_LIB, method_name)(value) ctrl_connection.send("{0} to {1}:{2}".format(tag, value, ret)) except AttributeError as e: logger.warning(str(e))
def process_command(cls, command, ctrl_connection, is_tx: bool): is_rx = not is_tx if command == cls.Command.STOP.name: return cls.Command.STOP.name tag, value = command try: if isinstance(cls.DEVICE_METHODS[tag], str): method_name = cls.DEVICE_METHODS[tag] elif isinstance(cls.DEVICE_METHODS[tag], dict): method_name = cls.DEVICE_METHODS[tag]["rx" if is_rx else "tx"] else: method_name = None except KeyError: method_name = None if method_name: try: try: check_method_name = cls.DEVICE_METHODS[tag+"_get_allowed_values"] allowed_values = getattr(cls.DEVICE_LIB, check_method_name)() next_allowed = min(allowed_values, key=lambda x: abs(x-value)) if value != next_allowed: ctrl_connection.send("{}: {} not in range of supported values. Assuming {}".format( tag, value, next_allowed )) value = next_allowed except (KeyError, AttributeError): pass ret = getattr(cls.DEVICE_LIB, method_name)(value) ctrl_connection.send("{0} to {1}:{2}".format(tag, value, ret)) except AttributeError as e: logger.warning(str(e))
def calc_noise_threshold(self, noise_start: int, noise_end: int): NDIGITS = 4 try: return np.ceil(np.max(np.absolute(self.data[int(noise_start):int(noise_end)])) * 10 ** NDIGITS) / 10 ** NDIGITS except ValueError: logger.warning("Could not caluclate noise treshold for range {}-{}".format(int(noise_start),int(noise_end))) return self.noise_threshold
def read_receiving_queue(self): while self.is_receiving: try: while not self.queue.empty(): byte_buffer = self.queue.get() nsamples = len(byte_buffer) // self.BYTES_PER_SAMPLE if nsamples > 0: if self.current_recv_index + nsamples >= len(self.receive_buffer): if self.is_ringbuffer: self.current_recv_index = 0 if nsamples >= len(self.receive_buffer): logger.warning("Receive buffer too small, skipping {0:d} samples".format(nsamples-len(self.receive_buffer))) nsamples = len(self.receive_buffer) - 1 else: self.stop_rx_mode("Receiving buffer is full {0}/{1}".format(self.current_recv_index + nsamples, len(self.receive_buffer))) return end = nsamples*self.BYTES_PER_SAMPLE self.receive_buffer[self.current_recv_index:self.current_recv_index + nsamples] = \ self.unpack_complex(byte_buffer[:end], nsamples) old_index = self.current_recv_index self.current_recv_index += nsamples self.rcv_index_changed.emit(old_index, self.current_recv_index) except BrokenPipeError: pass time.sleep(0.01)
def set_device_bandwidth(self, bandwidth): if self.bandwidth_is_adjustable: super().set_device_bandwidth(bandwidth) else: logger.warning( "Setting the bandwidth is not supported by your RTL-SDR driver version." )
def load_installed_plugins(self): """ :rtype: list of Plugin """ result = [] plugin_dirs = [ d for d in os.listdir(self.plugin_path) if os.path.isdir(os.path.join(self.plugin_path, d)) ] settings = constants.SETTINGS for d in plugin_dirs: if d == "__pycache__": continue try: class_module = self.load_plugin(d) plugin = class_module() plugin.plugin_path = os.path.join(self.plugin_path, plugin.name) plugin.load_description() plugin.enabled = settings.value( plugin.name, type=bool) if plugin.name in settings.allKeys() else False result.append(plugin) except ImportError as e: logger.warning("Could not load plugin {0} ({1})".format(d, e)) continue return result
def from_xml(self, tag: ET.Element, participants, decoders=None, message_types=None): part_id = tag.get("participant_id", None) message_type_id = tag.get("message_type_id", None) self.modulator_indx = int(tag.get("modulator_index", self.modulator_indx)) self.pause = int(tag.get("pause", self.pause)) decoding_index = tag.get("decoding_index", None) if decoding_index: try: self.decoder = decoders[int(decoding_index)] except IndexError: pass if part_id: for participant in participants: if participant.id_match(part_id): self.participant = participant break if self.participant is None: logger.warning("No participant matched the id {0} from xml".format(part_id)) if message_type_id and message_types: for message_type in message_types: if message_type.id == message_type_id: self.message_type = message_type break message_type_tag = tag.find("message_type") if message_type_tag: self.message_type = MessageType.from_xml(message_type_tag)
def set_device_bandwidth(self, bandwidth): if hasattr(rtlsdr, "set_tuner_bandwidth"): self.parent_conn.send("tuner_bandwidth:{}".format(int(bandwidth))) else: logger.warning( "Setting the bandwidth is not supported by your RTL-SDR driver version." )
def __add_to_buffer(self, data: np.ndarray): n = len(data) if n + self.__current_buffer_index > len(self.__buffer): n = len(self.__buffer) - self.__current_buffer_index - 1 logger.warning("Buffer of protocol sniffer is full") self.__buffer[self.__current_buffer_index:self.__current_buffer_index + n] = data[:n] self.__current_buffer_index += n
def run(self): if self.data is None: self.init_recv_buffer() self.initialize_process() logger.info("Initialize receive socket") self.init_recv_socket() recv = self.socket.recv rcvd = b"" try: while not self.isInterruptionRequested(): try: rcvd += recv(32768) # Receive Buffer = 32768 Byte except (zmq.error.ContextTerminated, ConnectionResetError): self.stop( "Stopped receiving, because connection was reset.") return except OSError as e: # https://github.com/jopohl/urh/issues/131 logger.warning("Error occurred", str(e)) if len(rcvd) < 8: self.stop("Stopped receiving: No data received anymore") return if len(rcvd) % 8 != 0: continue try: tmp = np.fromstring(rcvd, dtype=np.complex64) len_tmp = len(tmp) if self.data is None: # seems to be sometimes None in rare cases self.init_recv_buffer() if self.current_index + len_tmp >= len(self.data): if self.is_ringbuffer: self.current_index = 0 if len_tmp >= len(self.data): self.stop("Receiving buffer too small.") else: self.stop("Receiving Buffer is full.") return self.data[self.current_index:self.current_index + len_tmp] = tmp self.current_index += len_tmp self.index_changed.emit(self.current_index - len_tmp, self.current_index) rcvd = b"" except ValueError: self.stop("Could not receive data. Is your Hardware ok?") except RuntimeError: logger.error("Receiver Thread crashed.")
def read_participants_from_xml_tag(root: ET.Element): try: participants = [] for parti_tag in root.find("participants").findall("participant"): participants.append(Participant.from_xml(parti_tag)) return participants except AttributeError: logger.warning("no participants found in xml") return []
def run(self): logger.debug("Spectrum Thread: Init Process") self.initalize_process() logger.debug("Spectrum Thread: Process Intialized") self.init_recv_socket() logger.debug("Spectrum Thread: Socket initialized") recv = self.socket.recv rcvd = b"" try: logger.debug("Spectrum Thread: Enter main loop") while not self.isInterruptionRequested(): try: rcvd += recv(32768) # Receive Buffer = 32768 Byte except (zmq.error.ContextTerminated, ConnectionResetError): self.stop("Stopped receiving, because connection was reset") return except OSError as e: # https://github.com/jopohl/urh/issues/131 logger.warning("Error occurred", str(e)) if len(rcvd) < 8: self.stop("Stopped receiving, because no data transmitted anymore") return if len(rcvd) % 8 != 0: continue try: tmp = np.fromstring(rcvd, dtype=np.complex64) len_tmp = len(tmp) if self.data is None: self.data = np.zeros(self.buf_size, dtype=np.complex64) # type: np.ndarray if self.current_index + len_tmp >= len(self.data): self.data[self.current_index:] = tmp[:len(self.data) - self.current_index] tmp = tmp[len(self.data) - self.current_index:] w = np.abs(np.fft.fft(self.data)) freqs = np.fft.fftfreq(len(w), 1 / self.sample_rate) idx = np.argsort(freqs) self.x = freqs[idx].astype(np.float32) self.y = w[idx].astype(np.float32) self.data = np.zeros(len(self.data), dtype=np.complex64) self.data[0:len(tmp)] = tmp self.current_index = len(tmp) continue self.data[self.current_index:self.current_index + len_tmp] = tmp self.current_index += len_tmp rcvd = b"" except ValueError: self.stop("Could not receive data. Is your Hardware ok?") except RuntimeError as e: logger.error("Spectrum thread crashed", str(e.args))
def read_participants_from_xml_tag(root: ET.Element): try: participants = [] for parti_tag in root.find("participants").findall("participant"): participants.append(Participant.from_xml(parti_tag)) return participants except AttributeError: logger.warning("no participants found in xml") return []
def set_label_value(message, label, decimal_value: int): lbl_len = label.end - label.start f_string = "{0:0" + str(lbl_len) + "b}" bits = f_string.format(decimal_value) if len(bits) > lbl_len: logger.warning("Value {0} too big for label {1}, bits truncated".format(decimal_value, label.name)) for i in range(lbl_len): message[label.start + i] = bool(int(bits[i]))
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 set_label_value(message, label, decimal_value: int): lbl_len = label.end - label.start f_string = "{0:0" + str(lbl_len) + "b}" bits = f_string.format(decimal_value) if len(bits) > lbl_len: logger.warning("Value {0} too big for label {1}, bits truncated".format(decimal_value, label.name)) for i in range(lbl_len): message[label.start + i] = bool(int(bits[i]))
def calc_noise_threshold(self, noise_start: int, noise_end: int): num_digits = 4 noise_start, noise_end = int(noise_start), int(noise_end) try: magnitudes = np.absolute(self.data[noise_start:noise_end]) maximum = np.max(magnitudes) return np.ceil(maximum * 10 ** num_digits) / 10 ** num_digits except ValueError: logger.warning("Could not calculate noise threshold for range {}-{}".format(noise_start, noise_end)) return self.noise_threshold
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 delete_range(self, start: int, end: int): mask = np.ones(self.num_samples, dtype=bool) mask[start:end] = False try: self._fulldata = self._fulldata[mask] self._qad = self._qad[mask] if self._qad is not None else None except IndexError as e: logger.warning("Could not delete data: " + str(e)) self.__invalidate_after_edit()
def device_send(cls, ctrl_connection: Connection, send_config: SendConfig, dev_parameters: OrderedDict): if not cls.init_device( ctrl_connection, is_tx=True, parameters=dev_parameters): ctrl_connection.send("failed to start tx mode") return False if cls.ASYNCHRONOUS: ret = cls.enter_async_send_mode(send_config.get_data_to_send) else: ret = cls.prepare_sync_send(ctrl_connection) if ret != 0: ctrl_connection.send("failed to start tx mode") return False exit_requested = False buffer_size = cls.CONTINUOUS_TX_CHUNK_SIZE if send_config.continuous else cls.SYNC_TX_CHUNK_SIZE if not cls.ASYNCHRONOUS and buffer_size == 0: logger.warning("Send buffer size is zero!") ctrl_connection.send("successfully started tx mode") while not exit_requested and not send_config.sending_is_finished(): if cls.ASYNCHRONOUS: try: time.sleep(0.5) except KeyboardInterrupt: pass else: cls.send_sync(send_config.get_data_to_send(buffer_size)) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=True) if result == cls.Command.STOP.name: exit_requested = True break if not cls.ASYNCHRONOUS: # Some Sync send calls (e.g. USRP) are not blocking, so we wait a bit here to ensure # that the send buffer on the SDR is cleared time.sleep(0.75) if exit_requested: logger.debug("{}: exit requested. Stopping sending".format( cls.__class__.__name__)) if send_config.sending_is_finished(): logger.debug("{}: sending is finished.".format( cls.__class__.__name__)) cls.shutdown_device(ctrl_connection, is_tx=True) ctrl_connection.close()
def delete_range(self, start: int, end: int): mask = np.ones(self.num_samples, dtype=bool) mask[start:end] = False try: self._fulldata = self._fulldata[mask] self._qad = self._qad[mask] if self._qad is not None else None except IndexError as e: logger.warning("Could not delete data: " + str(e)) self.__invalidate_after_edit()
def run(self): if self.data is None: self.init_recv_buffer() self.initialize_process() logger.info("Initialize receive socket") self.init_recv_socket() recv = self.socket.recv rcvd = b"" try: while not self.isInterruptionRequested(): try: rcvd += recv(32768) # Receive Buffer = 32768 Byte except zmq.error.Again: # timeout continue except (zmq.error.ContextTerminated, ConnectionResetError): self.stop("Stopped receiving, because connection was reset.") return except OSError as e: # https://github.com/jopohl/urh/issues/131 logger.warning("Error occurred", str(e)) if len(rcvd) < 8: self.stop("Stopped receiving: No data received anymore") return if len(rcvd) % 8 != 0: continue try: tmp = np.fromstring(rcvd, dtype=np.complex64) num_samples = len(tmp) if self.data is None: # seems to be sometimes None in rare cases self.init_recv_buffer() if self.current_index + num_samples >= len(self.data): if self.resume_on_full_receive_buffer: self.current_index = 0 if num_samples >= len(self.data): self.stop("Receiving buffer too small.") else: self.stop("Receiving Buffer is full.") return self.data[self.current_index:self.current_index + num_samples] = tmp self.current_index += num_samples rcvd = b"" except ValueError: self.stop("Could not receive data. Is your Hardware ok?") except RuntimeError: logger.error("Receiver Thread crashed.")
def gain(self, value): if value > self._max_gain: err = "{0} gain {1} too high. Correcting to {2}".format(type(self).__name__, value, self._max_gain) self.errors.add(err) logger.warning(err) value = self._max_gain if value != self.__gain: self.__gain = value if self.is_open: self.set_device_gain(value)
def stop_tx_mode(self, msg): self.is_transmitting = False try: self.send_buffer_reader.close() self.send_buffer.close() except AttributeError: logger.warning("HackRF: Could not close send buffer, because it was not open yet") if self.is_open: logger.info("stopping HackRF tx mode ({0})".format(msg)) logger.info("closing because stop_tx_mode of HackRF is bugged and never returns") self.close(exit=False)
def frequency(self, value): if value > self._max_frequency: err = "{0} frequency {1}Hz too high. Correcting to {2}Hz".format( type(self).__name__, Formatter.big_value_with_suffix(value), Formatter.big_value_with_suffix(self._max_frequency)) self.errors.add(err) logger.warning(err) value = self._max_frequency if value != self.__frequency: self.__frequency = value self.set_device_frequency(value)
def sample_rate(self, value): if value > self._max_sample_rate: err = "{0} sample rate {1}Sps too high. Correcting to {2}Sps".format( type(self).__name__, Formatter.big_value_with_suffix(value), Formatter.big_value_with_suffix(self._max_sample_rate)) self.errors.add(err) logger.warning(err) value = self._max_sample_rate if value != self.__sample_rate: self.__sample_rate = value self.set_device_sample_rate(value)
def __init__(self, raw_mode=False, resume_on_full_receive_buffer=False, spectrum=False, sending=False): """ :param raw_mode: If true, sending and receiving raw samples if false bits are received/sent """ super().__init__(name="NetworkSDRInterface") self.client_ip = self.qsettings.value("client_ip", defaultValue="127.0.0.1", type=str) self.server_ip = "" self.samples_to_send = None # set in virtual device constructor self.client_port = self.qsettings.value("client_port", defaultValue=2222, type=int) self.server_port = self.qsettings.value("server_port", defaultValue=4444, type=int) self.receive_check_timer = QTimer() self.receive_check_timer.setInterval(250) # need to make the connect for the time in constructor, as create connects is called elsewhere in base class self.receive_check_timer.timeout.connect(self.__emit_rcv_index_changed) self.is_in_spectrum_mode = spectrum self.resume_on_full_receive_buffer = resume_on_full_receive_buffer self.__is_sending = False self.__sending_interrupt_requested = False self.sending_repeats = 1 # only used in raw mode self.current_sent_sample = 0 self.current_sending_repeat = 0 self.sending_is_continuous = False self.continuous_send_ring_buffer = None self.num_samples_to_send = None # Only used for continuous send mode self.raw_mode = raw_mode if not sending: if self.raw_mode: num_samples = SettingsProxy.get_receive_buffer_size(self.resume_on_full_receive_buffer, self.is_in_spectrum_mode) try: self.receive_buffer = np.zeros(num_samples, dtype=np.complex64, order='C') except MemoryError: logger.warning("Could not allocate buffer with {0:d} samples, trying less...") i = 0 while True: try: i += 2 self.receive_buffer = np.zeros(num_samples // i, dtype=np.complex64, order='C') logger.debug("Using buffer with {0:d} samples instead.".format(num_samples // i)) break except MemoryError: continue else: self.received_bits = []
def calc_relative_noise_threshold_from_range(self, noise_start: int, noise_end: int): num_digits = 4 noise_start, noise_end = int(noise_start), int(noise_end) if noise_start > noise_end: noise_start, noise_end = noise_end, noise_start try: maximum = np.max(self.iq_array.subarray(noise_start, noise_end).magnitudes_normalized) return np.ceil(maximum * 10 ** num_digits) / 10 ** num_digits except ValueError: logger.warning("Could not calculate noise threshold for range {}-{}".format(noise_start, noise_end)) return self.noise_threshold_relative
def bandwidth(self, value): if value > self._max_bandwidth: err = "{0} bandwidth {1}Hz too high. Correcting to {2}Hz".format(type(self).__name__, Formatter.big_value_with_suffix(value), Formatter.big_value_with_suffix(self._max_bandwidth)) self.errors.add(err) logger.warning(err) value = self._max_bandwidth if value != self.__bandwidth: self.__bandwidth = value if self.is_open: self.set_device_bandwidth(value)
def calc_noise_threshold(self, noise_start: int, noise_end: int): num_digits = 4 noise_start, noise_end = int(noise_start), int(noise_end) if noise_start > noise_end: noise_start, noise_end = noise_end, noise_start try: magnitudes = np.absolute(self.data[noise_start:noise_end]) maximum = np.max(magnitudes) return np.ceil(maximum * 10 ** num_digits) / 10 ** num_digits except ValueError: logger.warning("Could not calculate noise threshold for range {}-{}".format(noise_start, noise_end)) return self.noise_threshold
def get_selected_label_index(self, row: int, column: int): if self.row_count == 0: return -1 try: msg = self.protocol.messages[row] except IndexError: logger.warning("{} is out of range for generator protocol".format(row)) return -1 for i, lbl in enumerate(msg.message_type): if column in range(*msg.get_label_range(lbl, self.proto_view, False)): return i return -1
def device_send(cls, ctrl_connection: Connection, send_config: SendConfig, dev_parameters: OrderedDict): if not cls.init_device(ctrl_connection, is_tx=True, parameters=dev_parameters): ctrl_connection.send("failed to start tx mode") return False if cls.ASYNCHRONOUS: ret = cls.enter_async_send_mode(send_config.get_data_to_send) else: ret = cls.prepare_sync_send(ctrl_connection) if ret != 0: ctrl_connection.send("failed to start tx mode") return False exit_requested = False buffer_size = cls.CONTINUOUS_TX_CHUNK_SIZE if send_config.continuous else cls.SYNC_TX_CHUNK_SIZE if not cls.ASYNCHRONOUS and buffer_size == 0: logger.warning("Send buffer size is zero!") ctrl_connection.send("successfully started tx mode") while not exit_requested and not send_config.sending_is_finished(): if cls.ASYNCHRONOUS: try: time.sleep(0.5) except KeyboardInterrupt: pass else: cls.send_sync(send_config.get_data_to_send(buffer_size)) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=True) if result == cls.Command.STOP.name: exit_requested = True break if not cls.ASYNCHRONOUS: # Some Sync send calls (e.g. USRP) are not blocking, so we wait a bit here to ensure # that the send buffer on the SDR is cleared time.sleep(0.75) if exit_requested: logger.debug("{}: exit requested. Stopping sending".format(cls.__class__.__name__)) if send_config.sending_is_finished(): logger.debug("{}: sending is finished.".format(cls.__class__.__name__)) cls.shutdown_device(ctrl_connection, is_tx=True) ctrl_connection.close()
def __init__(self, raw_mode=False, resume_on_full_receive_buffer=False, spectrum=False, sending=False): """ :param raw_mode: If true, sending and receiving raw samples if false bits are received/sent """ super().__init__(name="NetworkSDRInterface") self.client_ip = self.qsettings.value("client_ip", defaultValue="127.0.0.1", type=str) self.server_ip = "" self.samples_to_send = None # set in virtual device constructor self.client_port = self.qsettings.value("client_port", defaultValue=2222, type=int) self.server_port = self.qsettings.value("server_port", defaultValue=4444, type=int) self.is_in_spectrum_mode = spectrum self.resume_on_full_receive_buffer = resume_on_full_receive_buffer self.__is_sending = False self.__sending_interrupt_requested = False self.sending_repeats = 1 # only used in raw mode self.current_sent_sample = 0 self.current_sending_repeat = 0 self.sending_is_continuous = False self.continuous_send_ring_buffer = None self.num_samples_to_send = None # Only used for continuous send mode self.raw_mode = raw_mode if not sending: if self.raw_mode: num_samples = SettingsProxy.get_receive_buffer_size(self.resume_on_full_receive_buffer, self.is_in_spectrum_mode) try: self.receive_buffer = np.zeros(num_samples, dtype=np.complex64, order='C') except MemoryError: logger.warning("Could not allocate buffer with {0:d} samples, trying less...") i = 0 while True: try: i += 2 self.receive_buffer = np.zeros(num_samples // i, dtype=np.complex64, order='C') logger.debug("Using buffer with {0:d} samples instead.".format(num_samples // i)) break except MemoryError: continue else: self.received_bits = []
def write_packets(self, packets, filename: str, sample_rate: int): """ :type packets: list of Message :param filename: :return: """ if os.path.isfile(filename): logger.warning("{0} already exists. Overwriting it".format(filename)) with open(filename, "wb") as f: f.write(self.build_global_header()) with open(filename, "ab") as f: rel_time_offset_ns = 0 for pkt in packets: f.write(self.build_packet(0, rel_time_offset_ns, pkt.decoded_bits_buffer)) rel_time_offset_ns = pkt.get_duration(sample_rate) * 10 ** 9
def to_xml(self, decoders=None, include_message_type=False, write_bits=False) -> ET.Element: root = ET.Element("message") root.set("message_type_id", self.message_type.id) root.set("modulator_index", str(self.modulator_index)) root.set("pause", str(self.pause)) root.set("timestamp", str(self.timestamp)) if write_bits: root.set("bits", self.plain_bits_str) if decoders: try: decoding_index = decoders.index(self.decoder) except ValueError: logger.warning("Failed to find '{}' in list of decodings".format(self.decoder.name)) decoding_index = 0 root.set("decoding_index", str(decoding_index)) if self.participant is not None: root.set("participant_id", self.participant.id) if include_message_type: root.append(self.message_type.to_xml()) return root
def process_command(cls, command, ctrl_connection, is_tx: bool): is_rx = not is_tx if command == cls.Command.STOP.name: return cls.Command.STOP.name tag, value = command try: if isinstance(cls.DEVICE_METHODS[tag], str): method_name = cls.DEVICE_METHODS[tag] elif isinstance(cls.DEVICE_METHODS[tag], dict): method_name = cls.DEVICE_METHODS[tag]["rx" if is_rx else "tx"] else: method_name = None except KeyError: method_name = None if method_name: try: ret = getattr(cls.DEVICE_LIB, method_name)(value) ctrl_connection.send("{0} to {1}:{2}".format(tag, value, ret)) except AttributeError as e: logger.warning(str(e))
def __ensure_message_length_multiple(bit_data, bit_len: int, pauses, bit_sample_pos, divisor: int): """ In case of ASK modulation, this method tries to use pauses after messages as zero bits so that the bit lengths of messages are divisible by divisor :param bit_data: List of bit arrays :param bit_len: Bit length that was used for demodulation :param pauses: List of pauses :param bit_sample_pos: List of Array of bit sample positions :param divisor: Divisor the messages should be divisible by """ for i in range(len(bit_data)): missing_bits = (divisor - (len(bit_data[i]) % divisor)) % divisor if missing_bits > 0 and pauses[i] >= bit_len * missing_bits: bit_data[i].extend([0] * missing_bits) pauses[i] = pauses[i] - missing_bits * bit_len try: bit_sample_pos[i][-1] = bit_sample_pos[i][-2] + bit_len except IndexError as e: logger.warning("Error padding message " + str(e)) continue bit_sample_pos[i].extend([bit_sample_pos[i][-1] + (k + 1) * bit_len for k in range(missing_bits - 1)]) bit_sample_pos[i].append(bit_sample_pos[i][-1] + pauses[i])
def undo(self): if self.mode == EditAction.delete: self.signal._fulldata = np.insert(self.signal._fulldata, self.start, self.orig_data_part) if self.cache_qad and self.orig_qad_part is not None: try: self.signal._qad = np.insert(self.signal._qad, self.start, self.orig_qad_part) except ValueError: self.signal._qad = None logger.warning("Could not restore cached qad.") elif self.mode == EditAction.mute or self.mode == EditAction.filter: self.signal._fulldata[self.start:self.end] = self.orig_data_part if self.cache_qad and self.orig_qad_part is not None: try: self.signal._qad[self.start:self.end] = self.orig_qad_part except ValueError: self.signal._qad = None logger.warning("Could not restore cached qad.") elif self.mode == EditAction.crop: self.signal._fulldata = np.concatenate((self.pre_crop_data, self.signal._fulldata, self.post_crop_data)) if self.cache_qad: try: self.signal._qad = np.concatenate((self.pre_crop_qad, self.signal._qad, self.post_crop_qad)) except ValueError: self.signal._qad = None logger.warning("Could not restore cached qad.") elif self.mode == EditAction.paste or self.mode == EditAction.insert: self.signal.delete_range(self.position, self.position+len(self.data_to_insert)) self.signal.parameter_cache = self.orig_parameter_cache if self.protocol: self.protocol.messages = self.orig_messages self.protocol.qt_signals.protocol_updated.emit() self.signal.changed = self.signal_was_changed self.signal.data_edited.emit()
def remove(self, lbl: ProtocolLabel): if lbl in self: super().remove(lbl) else: logger.warning(lbl.name + " is not in set, so cant be removed")
def str2val(str_val, dtype, default=0): try: return dtype(str_val) except (ValueError, TypeError): logger.warning("The {0} is not a valid {1}, assuming {2}".format(str_val, str(dtype), str(default))) return default
def scrollContentsBy(self, dx: int, dy: int): try: super().scrollContentsBy(dx, dy) self.redraw_timer.start(0) except RuntimeError as e: logger.warning("Graphic View already closed: " + str(e))
def if_gain(self): try: return self.__dev.if_gain except AttributeError as e: logger.warning(str(e))
def if_gain(self, value): try: self.__dev.if_gain = value except AttributeError as e: logger.warning(str(e))
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
def operator_description(self, value): for key, val in OPERATION_DESCRIPTION.items(): if val == value: self.operator = key return logger.warning("Could not find operator description " + str(value))
def value_type(self, value: int): try: self.__value_type = int(value) except ValueError: logger.warning("{} could not be cast to integer".format(value))
def start(self, value: int): try: self.__start = int(value) except ValueError: logger.warning("{} could not be cast to integer".format(value))
def set_device_bandwidth(self, bandwidth): if self.bandwidth_is_adjustable: super().set_device_bandwidth(bandwidth) else: logger.warning("Setting the bandwidth is not supported by your RTL-SDR driver version.")