def test_cython_wrapper(): descs, uris = plutosdr.scan_devices() plutosdr.set_tx(False) print("Devices", descs) print("Open", plutosdr.open(uris[0])) print("Set Freq to 433.92e6", plutosdr.set_center_freq(int(433.92e6))) print("Set Sample Rate to 2M", plutosdr.set_sample_rate(int(2.5e6))) print("Set bandwidth to 4M", plutosdr.set_bandwidth(int(4e6))) print("Set gain to 10", plutosdr.set_rf_gain(10)) print("prepare rx", plutosdr.setup_rx()) parent_conn, child_conn = Pipe() for i in range(10): plutosdr.receive_sync(child_conn) data = parent_conn.recv_bytes() print(np.frombuffer(data, dtype=np.int16)) print(plutosdr.get_tx()) print("Close", plutosdr.close()) plutosdr.set_tx(True) print("Open", plutosdr.open(uris[0])) print("Setup tx", plutosdr.setup_tx()) print("Set Freq to 433.92e6", plutosdr.set_center_freq(int(433.92e6))) print("Set Sample Rate to 2M", plutosdr.set_sample_rate(int(2.5e6))) print("Set bandwidth to 4M", plutosdr.set_bandwidth(int(4e6))) print("Set gain to 10", plutosdr.set_rf_gain(-89)) print("Send", plutosdr.send_sync(np.zeros(4096, dtype=np.int16))) print("Close", plutosdr.close())
def sandbox_function(function, *args): """ Runs a function liable to cause a crash in a separate process. Args: function: the function to run. This function must return an array of strings OR exit with a non-zero status. args...: the arguments to be passed to the function Returns: The array of strings returned by the function. Raises: SandboxProcessFailure: the process the function was running in exited with a non-zero status (the exit code is included in the exception) """ EXIT_SUCCESS = 0 def function_wrapper(function, pipe_receiver, pipe_sender, args): """ This function calls the user's function and then sends the returned data back on the provided pipe. """ pipe_receiver.close() results = function(*args) for result in results: pipe_sender.send_bytes(result) pipe_sender.close() # Create a pipe to send data returned from the function. This custom # serialization scheme is used because at least one application of the # sandbox uses untrusted data unsuitable for pickling. If more diverse # applications crop up, using JSON for serialization may make sense. pipe_receiver, pipe_sender = Pipe(duplex=False) # Call the function wrapper in a new process process = Process(target=function_wrapper, args=(function, pipe_receiver, pipe_sender, args)) process.start() pipe_sender.close() # Reconstruct the returned data results = [] while True: try: result = pipe_receiver.recv_bytes() results.append(result) except EOFError: break # Wait for the new process to exit process.join() # The status code will be non-zero on a crash or exception if process.exitcode is not EXIT_SUCCESS: raise SandboxProcessFailure(process.exitcode) return results
def test_multiprocessing_pipe(self): parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() for _ in range(5): while parent_conn.poll(): print("Got from client", parent_conn.recv_bytes()) # prints "[42, None, 'hello']" time.sleep(1) parent_conn.send_bytes(b"stop") p.join()
def test_multiprocessing_pipe(self): parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn, )) p.start() for _ in range(5): while parent_conn.poll(): print("Got from client", parent_conn.recv_bytes()) # prints "[42, None, 'hello']" time.sleep(1) parent_conn.send_bytes(b"stop") p.join()
def create_proof_of_time_nwesolowski(discriminant, x, iterations, int_size_bits, depth_limit, depth=0): """ Returns a serialized proof blob, using n_wesolowski iterations_1 iterations_2 proof_2 [----------------------------------------------|---------------------][-----] |---------------------] proof_1 """ L, k, w = proof_wesolowski.approximate_parameters(iterations) iterations_1 = (iterations * w) // (w + 1) iterations_2 = iterations - iterations_1 identity = ClassGroup.identity_for_discriminant(discriminant) powers_to_calculate = [ i * k * L for i in range(0, math.ceil(iterations_1 / (k * L)) + 1) ] powers_to_calculate += [iterations_1] powers = iterate_squarings(x, powers_to_calculate) y_1 = powers[iterations_1] receive_con, send_con = Pipe(False) p = Process(target=proof_wesolowski.generate_proof, args=(identity, x, y_1, iterations_1, k, L, powers, send_con)) p.start() if (depth < depth_limit - 1): y_2, proof_2 = create_proof_of_time_nwesolowski( discriminant, y_1, iterations_2, int_size_bits, depth_limit, depth + 1) else: y_2, proof_2 = create_proof_of_time_wesolowski(discriminant, y_1, iterations_2, int_size_bits) proof = ClassGroup.from_bytes(receive_con.recv_bytes(), discriminant) p.join() return y_2, proof_2 + iterations_1.to_bytes( 8, byteorder="big") + serialize_proof([y_1, proof])
class HttpBowler(Bowler): def __init__(self): Bowler.__init__(self) self._data_q, another_data_end = Pipe() self._command_q, another_command_end = Pipe() self._bridge = Process(target=build_bridge, args=(another_data_end, another_command_end)) self._bridge.start() def _msg_generator(self): while True: while self._data_q.poll(): try: logger.info('Receive ad data') data = str(self._data_q.recv_bytes(), encoding='utf-8') yield json.loads(data) except Exception as e: logger.error(e) time.sleep(5)
def notify_sound(self): #false arg makes unidirectional connection from_mic, to_volume = Pipe(False) self.mic_source.listeners['volume'] = to_volume last_rms = False logger.info('notify sound thread started') sound_count = 0 volume_threshold = self.conf['volume_threshold'] while not self.stop_thread.is_set(): data = from_mic.recv_bytes() rms = audioop.rms(data, 2) logger.debug('notify sound got rms %d', rms) if rms > volume_threshold: sound_count += 1 logger.debug('incrementing sound_count %s', sound_count) #idea is if 3 consecutive .recv_bytes are above threshold #we send message (this is to exit out of hold_repeater mode) #if you modify the config for the mic this may be too long or too short if rms > volume_threshold and sound_count >= 3: logger.debug( 'got extended sound, sending SOUND_EXTENDED msg to main q') msg = json.dumps({"volume_monitor": "SOUND_EXTENDED"}) self.main_q.put(msg) if rms > volume_threshold and not last_rms: last_rms = True logger.debug("got first loud rms: %d", rms) msg = json.dumps({"volume_monitor": "SOUND_ON"}) self.main_q.put(msg) if rms <= volume_threshold and last_rms: last_rms = False sound_count = 0 logger.debug("got quiet: %d", rms) msg = json.dumps({"volume_monitor": "SOUND_OFF"}) self.main_q.put(msg) else: logger.debug("got rms: %d", rms) #note- if getting odd bugs it's probably a race condition here del self.mic_source.listeners['volume'] to_volume.close() from_mic.close() to_volume = None from_mic = None logger.info('notify sound thread stopped')
def test_cython_wrapper(self): result = airspy.open() print("Open:", airspy.error_name(result), result) sample_rates = airspy.get_sample_rates() print("Samples rates:", sample_rates) result = airspy.set_sample_rate(10**6) print("Set sample rate", airspy.error_name(result), result) result = airspy.set_center_frequency(int(433.92e6)) print("Set center frequency", airspy.error_name(result), result) result = airspy.set_if_rx_gain(5) print("Set lna gain", airspy.error_name(result), result) result = airspy.set_rf_gain(8) print("Set mixer gain", airspy.error_name(result), result) result = airspy.set_baseband_gain(10) print("Set vga gain", airspy.error_name(result), result) parent_conn, child_conn = Pipe() result = airspy.start_rx(child_conn.send_bytes) print("Set start rx", airspy.error_name(result), result) time.sleep(0.01) print(np.fromstring(parent_conn.recv_bytes(8*65536), dtype=np.complex64)) print("Closing") parent_conn.close() child_conn.close() result = airspy.stop_rx() print("Set stop rx", airspy.error_name(result), result) result = airspy.close() print("Close:", airspy.error_name(result), result)
def run(ls): start = datetime.now() tmp = [] for fn, args, kwargs in ls: parent_conn, child_conn = Pipe() p = Process(target=process_wrapper, args=(fn, child_conn) + args, kwargs=kwargs) p.start() tmp.append((p, parent_conn, child_conn)) result = [] for p, parent_conn, child_conn in tmp: result.append(parent_conn.recv_bytes()) p.join() parent_conn.close() child_conn.close() execution_time = datetime.now() - start print("Время работы: " + str(execution_time.total_seconds()) + ' секунд') return result
def index(self, trans, mako = 'analyze', **kwd): if kwd.has_key('rerun_hda_id'): self._import_job_params(trans, kwd['rerun_hda_id']) my_end, your_end = Pipe() if isinstance(mako, list): mako = mako[0] proc = Process(target=self.__index_pipe, args=(your_end,trans,str(mako))) proc.start() html = '' if proc.is_alive(): if my_end.poll(120): html = my_end.recv_bytes() my_end.close() else: log.warn('fork timed out after 120 sec') else: log.warn('fork died on startup') proc.join(1) if proc.is_alive(): proc.terminate() log.warn('fork did not exit, terminated.') return html
def total(): # Parent. nums = [1 for _ in range(1000000)] chunk_size = len(nums) // 10 readers = [] pids = [] # break down hard problem while nums: chunk, nums = nums[:chunk_size], nums[chunk_size:] reader, writer = Pipe() # spwan (windows) or fork(Unix) process p = Process(target=Subtotal, args=(chunk, writer)) pids.append(p) readers.append(reader) # start child process for p in pids: p.start() # wait for child process until finish its job for p in pids: p.join() # get total total = 0 for reader in readers: subtotal = int(reader.recv_bytes().decode()) total += subtotal print("Total: %d" % total) # kill child process for p in pids: print('terminate pid', p.pid) p.terminate() print('pid %d is alive? %s' % (p.pid, p.is_alive()))
w_h.close() print(r_h.read()) r_h.close() os.unlink('/tmp/fifo') # Pipe/message ################################################### # Like message, can send and receive picklable objects. # Implemented by pipe or socket. p1, p2 = Pipe() p1.send([1, 2, 'a']) print(p2.recv()) p2.send_bytes('hello world', 6, 5) # offset=6, size=5 print(p1.recv_bytes()) # get 'world' p1.close() p2.close() # Queue ########################################################## # The object is stored in collections.deque temporarily. # A thread is running background, writing the object into # Pipe. So, object should be picklable. pool = Queue() pool.put(['a', 1]) print(pool.get(True)) # mmap and shared memory ######################################### # call map with MAP-SHARED before calling fork
class LocalCommunicator(Communicator, Pollable): def __init__(self): super().__init__() # locks write pipe self.__address_lock = Lock() self.__neighbors_lock = Lock() # one way pipe R, W self.__closed = False self.__mailbox, self.__address = Pipe(False) self.__neighbors = set() def send(self, data, timeout=None): closed_neighbors = [] with self.__neighbors_lock: if self.__closed: raise EOFError # self is closed # iterate through neighbors and deliver data to them for n in self.__neighbors: try: n.deliver(data) except (OSError, EOFError): # node is closed closed_neighbors.append(n) # remove closed neighbors for n in closed_neighbors: self.__neighbors.remove(n) def deliver(self, data): if self.__closed: raise EOFError with self.__address_lock: if select.select([], [self.__address], [], 0) != []: # can send bytes on pipe self.__address.send_bytes(data) def recv(self, timeout=None): # timeout in-accurate when looping if self.__neighbors is None: raise EOFError try: if self.__mailbox.poll(timeout=timeout): # poll mailbox # theres something in the mail! return self.__mailbox.recv_bytes() else: # timeout ended return b"" # not data received except (OSError, EOFError): raise EOFError # socket is closed def close(self): self.__closed = True self.__address.close() def send_filenos(self): return ([], [self.__address], []) # always ready to send! def recv_filenos(self): return ([self.__mailbox], [], []) def connect(self, comm): if self.__closed: raise EOFError with self.__neighbors_lock: self.__neighbors.add(comm) def disconnect(self, comm): with self.__neighbors_lock: try: self.__neighbors.remove(comm) except KeyError: pass # if you couldn't remove it don't worry
def is_prime(n): import math if n % 2 == 0: return False sqrt_n = int(math.sqrt(n)) a = [1 for i in range(3, sqrt_n + 1, 2) if n % i == 0] return False if sum(a) > 0 else True def main_p(primes, max_w=10): p = Pool(max_w) d = dict(zip(primes, p.map(is_prime, primes))) return d if __name__ == '__main__': print(main_p(list(range(3,98)))) #Process Pipe from multiprocessing import Pipe a, b = Pipe() a.send([1, 'hello', None]) b.recv() #[1, 'hello', None] b.send_bytes(b'thank you') a.recv_bytes() #b'thank you'
class AudioHandler(object): def __init__(self, callback, predictors: List[Predictor]): self.reader, self.writer = Pipe(False) self.exiter = Value('b', False) self.p: Process = None self.t: Thread = None self.buf = np.empty((0, ), dtype=np.float32) self.callback = callback self.predictors = predictors self.CHUNK = 1536 self.sleepy = (self.CHUNK / sr / 2) self.skippy = 0 def start(self): self.p = Process(target=AudioHandler._start_process, args=(self.CHUNK, self.writer, self.exiter)) self.p.start() self.t = Thread(target=self._start_thread) self.t.start() def _predict(self) -> Tuple[bool, int]: for predictor in self.predictors: sample_len = predictor.get_sample_len() if sample_len > self.buf.shape[0]: continue x = self.buf[:sample_len] x_transformed, _ = mfcc_transform(x, sr, input_dim) if predictor.predict(x_transformed): return True, predictor.get_sample_len() return False, 0 def _start_thread(self): min_sample_len = np.min([x.get_sample_len() for x in self.predictors]) skipping = False while not self.exiter.value: recv = np.frombuffer(self.reader.recv_bytes(), np.float32) self.buf = np.append(self.buf, recv) if self.skippy > 0: skipped = self.skippy if self.buf.shape[0] < skipped: skipped = self.buf.shape[0] self.skippy -= skipped self.buf = self.buf[skipped:] while self.skippy == 0 and self.buf.shape[0] > min_sample_len: if skipping: self.callback(False) skipping = False skipping, self.skippy = self._predict() if skipping: self.callback(True) self.buf = self.buf[self.CHUNK:] time.sleep(self.sleepy) @staticmethod def _start_process(chunk, conn: Connection, should_exit): def cb(in_data, frame_count, time_info, flag): conn.send_bytes(in_data) return None, pyaudio.paContinue def signal_cb(_, __): should_exit.value = True signal.signal(signal.SIGINT, signal_cb) p = pyaudio.PyAudio() print('process started') stream = p.open(format=pyaudio.paFloat32, channels=channels, rate=sr, input=True, output=False, stream_callback=cb, frames_per_buffer=chunk) while not should_exit.value: time.sleep(0.1) stream.close() p.terminate() def stop(self): self.exiter.value = True self.p.join() self.t.join()
class EnhancedQueue: """ Enhanced version of multiprocessing.Queue. Differences to multiprocessing.Queue ------------------------------------ - Arbitrarily large objects can be put onto the queue. The default implementation is limited by the buffer size of the underlying pipe: https://stackoverflow.com/a/45202335/1116842 """ def __init__( self, maxsize=0, encode=pickle.dumps, decode=pickle.loads, bufsize=1024 ): if maxsize <= 0: maxsize = multiprocessing.synchronize.SEM_VALUE_MAX self._encode = encode self._decode = decode self._bufsize = bufsize self._sem = multiprocessing.BoundedSemaphore(maxsize) # Items are enqueued in this buffer before the feeder thread sends them over the pipe self._buffer = collections.deque() self._reader, self._writer = Pipe(duplex=False) # Notify _feeder that an item is in the buffer self._notempty = threading.Condition() # _feeder thread self._thread = None self._writelock = multiprocessing.Lock() self._readlock = multiprocessing.Lock() def put(self, obj, block=True, timeout=None): if not self._sem.acquire(block, timeout): raise Full # Put obj into buffer. It will be encoded in a separate thread. with self._notempty: if self._thread is None: self._start_thread() self._buffer.append(obj) self._notempty.notify() def get(self, block=True, timeout=None): # Read from pipe if block and timeout is None: with self._readlock: buf = [] while True: chunk = self._reader.recv_bytes() if not chunk: break buf.append(chunk) buf = b"".join(buf) self._sem.release() return self._decode(buf) raise NotImplementedError() @staticmethod def _feeder( buffer: collections.deque, notempty: threading.Condition, writelock: multiprocessing.synchronize.Lock, writer: multiprocessing.connection.Connection, encode: Callable, bufsize: int, ): while True: with notempty: while not buffer: notempty.wait() obj = buffer.popleft() # TODO: Check sentinel # Serialize buf = encode(obj) with writelock: # Send data in bufsize chunks bytes_left = len(buf) while bytes_left > 0: bufsize = min(bytes_left, bufsize) writer.send_bytes(buf[-bytes_left:], 0, bufsize) bytes_left -= bufsize # Send empty value to signal end of buffer writer.send_bytes(b"") def _start_thread(self): """Start thread which transfers data from buffer to pipe.""" self._thread = threading.Thread( target=EnhancedQueue._feeder, args=( self._buffer, self._notempty, self._writelock, self._writer, self._encode, self._bufsize, ), name="EnhancedQueue._feeder", ) self._thread.daemon = True self._thread.start()
class Device(QObject): BYTES_PER_SAMPLE = None rcv_index_changed = pyqtSignal(int, int) def __init__(self, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseband_gain=1, is_ringbuffer=False): super().__init__() self.error_not_open = -4242 self.__bandwidth = bandwidth self.__frequency = center_freq self.__gain = gain # = rf_gain self.__if_gain = if_gain self.__baseband_gain = baseband_gain self.__sample_rate = sample_rate self.__freq_correction = 0 self.__direct_sampling_mode = 0 self.bandwidth_is_adjustable = True self._current_sent_sample = Value("L", 0) self._current_sending_repeat = Value("L", 0) self.success = 0 self.error_codes = {} self.device_messages = [] self.receive_process_function = None self.send_process_function = None self.parent_data_conn, self.child_data_conn = Pipe() self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.send_buffer = None self.send_buffer_reader = None self.samples_to_send = np.array([], dtype=np.complex64) self.sending_repeats = 1 # How often shall the sending sequence be repeated? 0 = forever self.is_ringbuffer = is_ringbuffer # Ringbuffer for Spectrum Analyzer or Protocol Sniffing self.current_recv_index = 0 self.is_receiving = False self.is_transmitting = False self.device_ip = "192.168.10.2" # For USRP and RTLSDRTCP self.receive_buffer = None self.spectrum_x = None self.spectrum_y = None def _start_read_rcv_buffer_thread(self): self.read_recv_buffer_thread = threading.Thread(target=self.read_receiving_queue) self.read_recv_buffer_thread.daemon = True self.read_recv_buffer_thread.start() def _start_read_message_thread(self): self.read_dev_msg_thread = threading.Thread(target=self.read_device_messages) self.read_dev_msg_thread.daemon = True self.read_dev_msg_thread.start() @property def current_sent_sample(self): return self._current_sent_sample.value // self.BYTES_PER_SAMPLE @current_sent_sample.setter def current_sent_sample(self, value: int): self._current_sent_sample.value = value * self.BYTES_PER_SAMPLE @property def current_sending_repeat(self): return self._current_sending_repeat.value @current_sending_repeat.setter def current_sending_repeat(self, value: int): self._current_sending_repeat.value = value @property def receive_process_arguments(self): return self.child_data_conn, self.child_ctrl_conn, self.frequency, self.sample_rate, self.bandwidth, self.gain, self.if_gain, self.baseband_gain @property def send_process_arguments(self): return self.child_ctrl_conn, self.frequency, self.sample_rate, self.bandwidth, \ self.gain, self.if_gain, self.baseband_gain, self.send_buffer, \ self._current_sent_sample, self._current_sending_repeat, self.sending_repeats def init_recv_buffer(self): if self.receive_buffer is None: if self.is_ringbuffer: num_samples = constants.SPECTRUM_BUFFER_SIZE else: # Take 60% of avail memory threshold = constants.SETTINGS.value('ram_threshold', 0.6, float) num_samples = threshold * (psutil.virtual_memory().available / 8) self.receive_buffer = np.zeros(int(num_samples), dtype=np.complex64, order='C') logger.info( "Initialized receiving buffer with size {0:.2f}MB".format(self.receive_buffer.nbytes / (1024 * 1024))) def log_retcode(self, retcode: int, action: str, msg=""): msg = str(msg) error_code_msg = self.error_codes[retcode] if retcode in self.error_codes else "Error Code: " + str(retcode) if retcode == self.success: if msg: formatted_message = "{0}-{1} ({2}): Success".format(type(self).__name__, action, msg) else: formatted_message = "{0}-{1}: Success".format(type(self).__name__, action) logger.info(formatted_message) else: if msg: formatted_message = "{0}-{1} ({4}): {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode, msg) else: formatted_message = "{0}-{1}: {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode) logger.error(formatted_message) self.device_messages.append(formatted_message) @property def received_data(self): return self.receive_buffer[:self.current_recv_index] @property def sent_data(self): return self.samples_to_send[:self.current_sent_sample] @property def sending_finished(self): return self.current_sent_sample == len(self.samples_to_send) @property def bandwidth(self): return self.__bandwidth @bandwidth.setter def bandwidth(self, value): if not self.bandwidth_is_adjustable: return if value != self.__bandwidth: self.__bandwidth = value self.set_device_bandwidth(value) def set_device_bandwidth(self, bw): try: self.parent_ctrl_conn.send("bandwidth:" + str(int(bw))) except BrokenPipeError: pass @property def frequency(self): return self.__frequency @frequency.setter def frequency(self, value): if value != self.__frequency: self.__frequency = value self.set_device_frequency(value) def set_device_frequency(self, value): try: self.parent_ctrl_conn.send("center_freq:" + str(int(value))) except BrokenPipeError: pass @property def gain(self): return self.__gain @gain.setter def gain(self, value): if value != self.__gain: self.__gain = value self.set_device_gain(value) def set_device_gain(self, gain): try: self.parent_ctrl_conn.send("rf_gain:" + str(int(gain))) except BrokenPipeError: pass @property def if_gain(self): return self.__if_gain @if_gain.setter def if_gain(self, value): if value != self.__if_gain: self.__if_gain = value self.set_device_if_gain(value) def set_device_if_gain(self, if_gain): try: self.parent_ctrl_conn.send("if_gain:" + str(int(if_gain))) except BrokenPipeError: pass @property def baseband_gain(self): return self.__baseband_gain @baseband_gain.setter def baseband_gain(self, value): if value != self.__baseband_gain: self.__baseband_gain = value self.set_device_baseband_gain(value) def set_device_baseband_gain(self, baseband_gain): try: self.parent_ctrl_conn.send("baseband_gain:" + str(int(baseband_gain))) except BrokenPipeError: pass @property def sample_rate(self): return self.__sample_rate @sample_rate.setter def sample_rate(self, value): if value != self.__sample_rate: self.__sample_rate = value self.set_device_sample_rate(value) def set_device_sample_rate(self, sample_rate): try: self.parent_ctrl_conn.send("sample_rate:" + str(int(sample_rate))) except BrokenPipeError: pass @property def freq_correction(self): return self.__freq_correction @freq_correction.setter def freq_correction(self, value): if value != self.__freq_correction: self.__freq_correction = value self.set_device_freq_correction(value) def set_device_freq_correction(self, value): try: self.parent_ctrl_conn.send("freq_correction:" + str(int(value))) except BrokenPipeError: pass @property def direct_sampling_mode(self): return self.__direct_sampling_mode @direct_sampling_mode.setter def direct_sampling_mode(self, value): if value != self.__direct_sampling_mode: self.__direct_sampling_mode = value self.set_device_direct_sampling_mode(value) def set_device_direct_sampling_mode(self, value): try: self.parent_ctrl_conn.send("direct_sampling_mode:" + str(int(value))) except BrokenPipeError: pass def start_rx_mode(self): self.init_recv_buffer() self.parent_data_conn, self.child_data_conn = Pipe() self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.is_receiving = True logger.info("{0}: Starting RX Mode".format(self.__class__.__name__)) self.receive_process = Process(target=self.receive_process_function, args=self.receive_process_arguments) self.receive_process.daemon = True self._start_read_rcv_buffer_thread() self._start_read_message_thread() try: self.receive_process.start() except OSError as e: logger.error(repr(e)) self.device_messages.add(repr(e)) def stop_rx_mode(self, msg): self.is_receiving = False try: self.parent_ctrl_conn.send("stop") except BrokenPipeError: pass logger.info("{0}: Stopping RX Mode: {1}".format(self.__class__.__name__, msg)) if hasattr(self, "receive_process") and self.receive_process.is_alive(): self.receive_process.join(0.5) if self.receive_process.is_alive(): logger.warning("{0}: Receive process is still alive, terminating it".format(self.__class__.__name__)) self.receive_process.terminate() self.receive_process.join() self.child_ctrl_conn.close() self.child_data_conn.close() def start_tx_mode(self, samples_to_send: np.ndarray = None, repeats=None, resume=False): self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.init_send_parameters(samples_to_send, repeats, resume=resume) self.is_transmitting = True logger.info("{0}: Starting TX Mode".format(self.__class__.__name__)) self.transmit_process = Process(target=self.send_process_function, args=self.send_process_arguments) self.transmit_process.daemon = True self._start_read_message_thread() self.transmit_process.start() def stop_tx_mode(self, msg): self.is_transmitting = False try: self.parent_ctrl_conn.send("stop") except BrokenPipeError: pass 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(0.5) 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.child_ctrl_conn.close() @staticmethod def unpack_complex(buffer, nvalues): pass @staticmethod def pack_complex(complex_samples: np.ndarray): pass def set_device_parameters(self): self.set_device_bandwidth(self.bandwidth) self.set_device_frequency(self.frequency) self.set_device_gain(self.gain) self.set_device_sample_rate(self.sample_rate) def read_device_messages(self): while self.is_receiving or self.is_transmitting: try: message = self.parent_ctrl_conn.recv() action, return_code = message.split(":") self.log_retcode(int(return_code), action) except (EOFError, UnpicklingError, ConnectionResetError): break self.is_transmitting = False self.is_receiving = False logger.debug("Exiting read device errors thread") def read_receiving_queue(self): while self.is_receiving: try: byte_buffer = self.parent_data_conn.recv_bytes() 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 except EOFError: logger.info("EOF Error: Ending receive thread") break time.sleep(0.01) logger.debug("Exiting read_receive_queue thread.") def init_send_parameters(self, samples_to_send: np.ndarray = None, repeats: int = None, skip_device_parameters=False, resume=False): if not skip_device_parameters: self.set_device_parameters() if samples_to_send is not None: self.samples_to_send = samples_to_send self.send_buffer = None if self.send_buffer is None: self.send_buffer = self.pack_complex(self.samples_to_send) elif not resume: self.current_sending_repeat = 0 if repeats is not None: self.sending_repeats = repeats
def test_cython_wrapper(self): print("Devices:", limesdr.get_device_list()) # print("Open:", limesdr.open("LimeSDR-USB, media=USB 3.0, module=STREAM, addr=1d50:6108, serial=0009060B0049180A")) print("Open:", limesdr.open()) print("-" * 20) print("Is Open 0:", limesdr.is_open(0)) print("Is Open 1:", limesdr.is_open(1)) print("Init", limesdr.init()) limesdr.set_tx(True) self.assertTrue(limesdr.get_tx()) #print(limesdr.IS_TX) print("Num Channels TX:", limesdr.get_num_channels()) print("TX antennas", limesdr.get_antenna_list()) limesdr.set_tx(False) self.assertFalse(limesdr.get_tx()) print("Num Channels RX:", limesdr.get_num_channels()) limesdr.CHANNEL = 0 print("Enable RX Channel 0:", limesdr.enable_channel(True, False, 0)) #path = os.path.realpath(os.path.join(__file__, "..", "..", "src", "urh", "dev", "native", "lime.ini")) #print(path) #limesdr.load_config(path) #limesdr.save_config("/tmp/lime_test.ini") clocks = [ "LMS_CLOCK_REF", "LMS_CLOCK_SXR", "LMS_CLOCK_SXT", "LMS_CLOCK_CGEN", "LMS_CLOCK_RXTSP", "LMS_CLOCK_TXTSP" ] for i, clock in enumerate(clocks): print(clock, limesdr.get_clock_freq(i)) limesdr.print_last_error() print("RX Sample Rate Range:", limesdr.get_sample_rate_range()) print("RX Channel 0 Sample Rate:", limesdr.get_sample_rate()) print("Set Sample Rate:", limesdr.set_sample_rate(2e6)) print("RX Channel 0 Sample Rate:", limesdr.get_sample_rate()) limesdr.print_last_error() print("RX Frequency Range:", limesdr.get_center_frequency_range()) print("RX 0 center freq:", limesdr.get_center_frequency()) print("RX 0 set center freq:", limesdr.set_center_frequency(433.92e6)) print("RX 0 center freq:", limesdr.get_center_frequency()) limesdr.print_last_error() print("RX 0 gain", limesdr.get_normalized_gain()) print("RX 0 set gain", limesdr.set_normalized_gain(0.5)) print("RX 0 gain", limesdr.get_normalized_gain()) limesdr.print_last_error() print("RX Bandwidth Range", limesdr.get_lpf_bandwidth_range()) print("RX 0 Bandwidth", limesdr.get_lpf_bandwidth()) print("RX 0 set Bandwidth", limesdr.set_lpf_bandwidth(20e6)) print("RX 0 Bandwidth", limesdr.get_lpf_bandwidth()) limesdr.print_last_error() print("RX 0 calibrate:", limesdr.calibrate(20e6)) limesdr.print_last_error() antenna_list = limesdr.get_antenna_list() print("RX 0 antenna list", antenna_list) print("RX 0 current antenna", limesdr.get_antenna(), antenna_list[limesdr.get_antenna()]) print("RX 0 current antenna BW", limesdr.get_antenna_bw(limesdr.get_antenna())) print("Chip Temperature", limesdr.get_chip_temperature()) parent_conn, child_conn = Pipe() for _ in range(2): limesdr.print_last_error() print("Setup stream", limesdr.setup_stream(1000)) print("Start stream", limesdr.start_stream()) limesdr.recv_stream(child_conn, 1000, 100) print("Stop stream", limesdr.stop_stream()) print("Destroy stream", limesdr.destroy_stream()) print(parent_conn.recv_bytes()) limesdr.set_tx(True) self.assertTrue(limesdr.get_tx()) samples_to_send = np.ones(32768, dtype=np.complex64) for _ in range(2): limesdr.print_last_error() print("Setup stream", limesdr.setup_stream(4000000000)) print("Start stream", limesdr.start_stream()) print("Send samples", limesdr.send_stream(samples_to_send, 100)) print("Stop stream", limesdr.stop_stream()) print("Destroy stream", limesdr.destroy_stream()) print("-" * 20) print("Close:", limesdr.close()) print("Is Open 0:", limesdr.is_open(0)) print("Is Open 1:", limesdr.is_open(1))
class MyClient(WebSocketClient): def __init__(self, url, protocols=None, extensions=None, heartbeat_freq=None, byterate=16000, show_hypotheses=True, save_adaptation_state_filename=None, send_adaptation_state_filename=None, audio_gate=0, out_q=None, in_q=None): super(MyClient, self).__init__(url, protocols, extensions, heartbeat_freq) self.show_hypotheses = show_hypotheses self.byterate = byterate self.save_adaptation_state_filename = save_adaptation_state_filename self.send_adaptation_state_filename = send_adaptation_state_filename self.chunk = 0 #note setting a gate value seems to mess with the adaption state and lead to poor recognition self.audio_gate = audio_gate self.out_q = out_q self.in_q = in_q def send_data(self, data): self.send(data, binary=True) def opened(self): self.from_mic, self.to_websocket = Pipe(False) mic_source.listeners['websock'] = self.to_websocket if self.out_q: self.out_q.put(json.dumps({'notify': 'Connected to Kaldi'})) def mic_to_ws(): try: logger.info("LISTENING TO MICROPHONE") last_state = None while True: if self.in_q and not self.in_q.empty(): change_decoder_msg = self.in_q.get() self.send(change_decoder_msg) try: data = self.from_mic.recv_bytes() except EOFError as e: #careful of order of cleaning up for reconnections or you #try to read from a closed pipe logger.exception("error reading from_mic pipe") if self.audio_gate > 0: rms = audioop.rms(data, 2) if rms < self.audio_gate: data = '\00' * len(data) #old silvius stuff, has always been commented out afaik #sample_rate = self.byterate # if sample_chan == 2: # data = audioop.tomono(data, 2, 1, 1) # if sample_rate != self.byterate: # (data, last_state) = audioop.ratecv(data, 2, 1, sample_rate, self.byterate, last_state) self.send_data(data) except IOError as e: # usually a broken pipe logger.warning("IOError") except AttributeError: # currently raised when the socket gets closed by main thread logger.warning( "AttributeError, likely socket closed by main thread") pass # to voluntarily close the connection, we would use #self.send_data("") #self.send("EOS") try: self.remove_mic_listener() self.close() except IOError: logger.warning("IOError, likely socket closed by main thread") pass threading.Thread(target=mic_to_ws).start() def remove_mic_listener(self): logger.info('removing web socket mic listener') self.from_mic.close() self.to_websocket.close() self.from_mic = None self.to_websocket = None del mic_source.listeners['websock'] def received_message(self, m): logger.debug("websocket received message %s", m) response = json.loads(str(m)) if response['status'] == 0: sys.stdout.flush() if self.out_q: self.out_q.put(str(m)) else: # text = response['result']['hypotheses'][0]['transcript'] print(response) #Silviux: adaption state is entirely handled on server now # if 'adaptation_state' in response: # if self.save_adaptation_state_filename: # logger.info("Saving adaptation state to %s", self.save_adaptation_state_filename) # with open(self.save_adaptation_state_filename, "w") as f: # f.write(json.dumps(response['adaptation_state'])) else: logger.error("Received error from server (status %d)", response['status']) if 'message' in response: logger.error("Error message: %s", response['message']) def closed(self, code, reason=None): logger.info("Websocket closed() called %s %s", code, reason) pass
class Client(APIClient): _agency = 'wxext' def __init__(self, account=None): APIClient.__init__(self, account) self._data_q, another_data_end = Pipe() self._command_q, another_command_end = Pipe() # start server to receive data from wx-retinue self._bridge = Process(target=build_bridge, args=(another_data_end, another_command_end)) self._bridge.start() def perform(self, commands): ''' :param commands: [ { "campaign_id": 1 "action": "suspend", "value": None }, { "campaign_id": 2 "action": "timeset_end", "value": 6 } ] :return: ''' self._command_q.send(commands) @staticmethod def transformer(original_data): rtn = {'agency': 'wxext'} reversed_keys = [ 'total_cost', 'view_count', 'sy_cost', 'update_time', 'cname' ] map_key = { 'cid': 'campaign_id', } # rtn['update_time'] = pendulum.from_format(original_data['update_time'], '%Y%m%d%H%M').to_datetime_string() for key in reversed_keys: rtn[key] = original_data[key] for key in map_key: rtn[map_key[key]] = original_data[key] rtn['click_count'] = original_data['click_url_count'] + original_data[ 'click_pic_count'] if original_data['real_status'] == '投放中': rtn['status'] = ADSTATUS_NORMAL elif original_data['real_status'] == '暂停投放': rtn['status'] = ADSTATUS_SUSPEND else: rtn['status'] = ADSTATUS_UNKNOW return rtn def statistic(self): while True: while self._data_q.poll(): try: data = str(self._data_q.recv_bytes(), encoding='utf-8') resp = json.loads(data) if resp['type'] == TYPE_CAMP_INFO: ''' Report campaign info ''' logger.info('Receive campaigns info') self.report_camp_info( resp['data']['account'], json.loads(resp['data']['campaigns'])) logger.info('Send campaign data to kafka successfully') elif resp['type'] == TYPE_ACTION_RES: ''' Report action result { id: 1, resp_cnt: 'success', resp_status: 200 } ''' logger.info('Receive action perform results') data = resp['data'] self.report_cmd_res(data['id'], data['resp_cnt'], data['resp_status']) logger.info( 'Send action results to kafka successfully') elif resp['type'] == TYPE_STATISTIC: '''' Report statistic { data: [ {}, {} ], account: 'myaccount', 'update_hour: '201804151005' } ''' resp = resp['data'] logger.info('Receive statistic info') processed_data = [] update_at = pendulum.from_format( resp['update_hour'], '%Y%m%d%H%M').to_datetime_string() for record in resp['data']: record['update_time'] = update_at record['account'] = resp['account'] processed_data.append(self.transformer(record)) self.report_statistic(resp['account'], { 'data': processed_data, 'update_time': update_at }) logger.info('Send ad data to kafka successfully') except Exception as e: logger.error('Exception raised when send data to kafka') logger.error(e) time.sleep(5) def quit(self): self._bridge.terminate()
class Device(QObject): SEND_BUFFER_SIZE = 0 CONTINUOUS_SEND_BUFFER_SIZE = 0 class Command(Enum): STOP = 0 SET_FREQUENCY = 1 SET_SAMPLE_RATE = 2 SET_BANDWIDTH = 3 SET_RF_GAIN = 4 SET_IF_GAIN = 5 SET_BB_GAIN = 6 SET_DIRECT_SAMPLING_MODE = 7 SET_FREQUENCY_CORRECTION = 8 SET_CHANNEL_INDEX = 9 SET_ANTENNA_INDEX = 10 BYTES_PER_SAMPLE = None rcv_index_changed = pyqtSignal(int, int) ASYNCHRONOUS = False DEVICE_LIB = None DEVICE_METHODS = { Command.SET_FREQUENCY.name: "set_center_freq", Command.SET_SAMPLE_RATE.name: "set_sample_rate", Command.SET_BANDWIDTH.name: "set_bandwidth", Command.SET_RF_GAIN.name: "set_rf_gain", Command.SET_IF_GAIN.name: {"rx": "set_if_rx_gain", "tx": "set_if_tx_gain"}, Command.SET_BB_GAIN.name: {"rx": "set_baseband_gain"} } @classmethod 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)) @classmethod def setup_device(cls, ctrl_connection: Connection, device_identifier): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def init_device(cls, ctrl_connection: Connection, is_tx: bool, parameters: OrderedDict) -> bool: if "identifier" in parameters: identifier = parameters["identifier"] else: identifier = None if cls.setup_device(ctrl_connection, device_identifier=identifier): for parameter, value in parameters.items(): cls.process_command((parameter, value), ctrl_connection, is_tx) return True else: return False @classmethod def adapt_num_read_samples_to_sample_rate(cls, sample_rate: float): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def shutdown_device(cls, ctrl_connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_receive_mode(cls, data_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_receive(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def receive_sync(cls, data_conn: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_send_mode(cls, callback: object): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_send(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def send_sync(cls, data): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def device_receive(cls, data_connection: Connection, ctrl_connection: Connection, dev_parameters: OrderedDict): if not cls.init_device(ctrl_connection, is_tx=False, parameters=dev_parameters): return False try: cls.adapt_num_read_samples_to_sample_rate(dev_parameters[cls.Command.SET_SAMPLE_RATE.name]) except NotImplementedError: # Many SDRs like HackRF or AirSpy do not need to calculate READ_SAMPLES # as default values are either fine or given by the hardware pass if cls.ASYNCHRONOUS: cls.enter_async_receive_mode(data_connection) else: cls.prepare_sync_receive(ctrl_connection) exit_requested = False while not exit_requested: if cls.ASYNCHRONOUS: time.sleep(0.5) else: cls.receive_sync(data_connection) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=False) if result == cls.Command.STOP.name: exit_requested = True break cls.shutdown_device(ctrl_connection) data_connection.close() ctrl_connection.close() @classmethod 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 __init__(self, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseband_gain=1, resume_on_full_receive_buffer=False): super().__init__() self.error_not_open = -4242 self.__bandwidth = bandwidth self.__frequency = center_freq self.__gain = gain # = rf_gain self.__if_gain = if_gain self.__baseband_gain = baseband_gain self.__sample_rate = sample_rate self.__channel_index = 0 self.__antenna_index = 0 self.__freq_correction = 0 self.__direct_sampling_mode = 0 self.bandwidth_is_adjustable = True self.is_in_spectrum_mode = False self.sending_is_continuous = False self.continuous_send_ring_buffer = None self.total_samples_to_send = None # None = get automatically. This value needs to be known in continuous send mode self._current_sent_sample = Value("L", 0) self._current_sending_repeat = Value("L", 0) self.success = 0 self.error_codes = {} self.device_messages = [] self.receive_process_function = self.device_receive self.send_process_function = self.device_send self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.send_buffer = None self.send_buffer_reader = None self.samples_to_send = np.array([], dtype=np.complex64) self.sending_repeats = 1 # How often shall the sending sequence be repeated? 0 = forever self.resume_on_full_receive_buffer = resume_on_full_receive_buffer # for Spectrum Analyzer or Protocol Sniffing self.current_recv_index = 0 self.is_receiving = False self.is_transmitting = False self.device_ip = "192.168.10.2" # For USRP and RTLSDRTCP self.receive_buffer = None self.spectrum_x = None self.spectrum_y = None def _start_read_rcv_buffer_thread(self): self.read_recv_buffer_thread = threading.Thread(target=self.read_receiving_queue) self.read_recv_buffer_thread.daemon = True self.read_recv_buffer_thread.start() def _start_read_message_thread(self): self.read_dev_msg_thread = threading.Thread(target=self.read_device_messages) self.read_dev_msg_thread.daemon = True self.read_dev_msg_thread.start() @property def current_sent_sample(self): return self._current_sent_sample.value // 2 @current_sent_sample.setter def current_sent_sample(self, value: int): self._current_sent_sample.value = value * 2 @property def current_sending_repeat(self): return self._current_sending_repeat.value @current_sending_repeat.setter def current_sending_repeat(self, value: int): self._current_sending_repeat.value = value @property def device_parameters(self) -> OrderedDict: return OrderedDict([(self.Command.SET_FREQUENCY.name, self.frequency), (self.Command.SET_SAMPLE_RATE.name, self.sample_rate), (self.Command.SET_BANDWIDTH.name, self.bandwidth), (self.Command.SET_RF_GAIN.name, self.gain), (self.Command.SET_IF_GAIN.name, self.if_gain), (self.Command.SET_BB_GAIN.name, self.baseband_gain)]) @property def send_config(self) -> SendConfig: total_samples = len(self.send_buffer) if self.total_samples_to_send is None else 2 * self.total_samples_to_send return SendConfig(self.send_buffer, self._current_sent_sample, self._current_sending_repeat, total_samples, self.sending_repeats, continuous=self.sending_is_continuous, pack_complex_method=self.pack_complex, continuous_send_ring_buffer=self.continuous_send_ring_buffer) @property def receive_process_arguments(self): return self.child_data_conn, self.child_ctrl_conn, self.device_parameters @property def send_process_arguments(self): return self.child_ctrl_conn, self.send_config, self.device_parameters def init_recv_buffer(self): if self.receive_buffer is None: num_samples = SettingsProxy.get_receive_buffer_size(self.resume_on_full_receive_buffer, self.is_in_spectrum_mode) self.receive_buffer = np.zeros(int(num_samples), dtype=np.complex64, order='C') def log_retcode(self, retcode: int, action: str, msg=""): msg = str(msg) error_code_msg = self.error_codes[retcode] if retcode in self.error_codes else "Error Code: " + str(retcode) if retcode == self.success: if msg: formatted_message = "{0}-{1} ({2}): Success".format(type(self).__name__, action, msg) else: formatted_message = "{0}-{1}: Success".format(type(self).__name__, action) logger.info(formatted_message) else: if msg: formatted_message = "{0}-{1} ({4}): {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode, msg) else: formatted_message = "{0}-{1}: {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode) logger.error(formatted_message) self.device_messages.append(formatted_message) @property def received_data(self): return self.receive_buffer[:self.current_recv_index] @property def sent_data(self): return self.samples_to_send[:self.current_sent_sample] @property def sending_finished(self): return self.current_sent_sample == len(self.samples_to_send) @property def bandwidth(self): return self.__bandwidth @bandwidth.setter def bandwidth(self, value): if not self.bandwidth_is_adjustable: return if value != self.__bandwidth: self.__bandwidth = value self.set_device_bandwidth(value) def set_device_bandwidth(self, bw): try: self.parent_ctrl_conn.send((self.Command.SET_BANDWIDTH.name, int(bw))) except (BrokenPipeError, OSError): pass @property def frequency(self): return self.__frequency @frequency.setter def frequency(self, value): if value != self.__frequency: self.__frequency = value self.set_device_frequency(value) def set_device_frequency(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_FREQUENCY.name, int(value))) except (BrokenPipeError, OSError): pass @property def gain(self): return self.__gain @gain.setter def gain(self, value): if value != self.__gain: self.__gain = value self.set_device_gain(value) def set_device_gain(self, gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_RF_GAIN.name, gain)) except (BrokenPipeError, OSError): pass @property def if_gain(self): return self.__if_gain @if_gain.setter def if_gain(self, value): if value != self.__if_gain: self.__if_gain = value self.set_device_if_gain(value) def set_device_if_gain(self, if_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_IF_GAIN.name, if_gain)) except (BrokenPipeError, OSError): pass @property def baseband_gain(self): return self.__baseband_gain @baseband_gain.setter def baseband_gain(self, value): if value != self.__baseband_gain: self.__baseband_gain = value self.set_device_baseband_gain(value) def set_device_baseband_gain(self, baseband_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_BB_GAIN.name, baseband_gain)) except (BrokenPipeError, OSError): pass @property def sample_rate(self): return self.__sample_rate @sample_rate.setter def sample_rate(self, value): if value != self.__sample_rate: self.__sample_rate = value self.set_device_sample_rate(value) def set_device_sample_rate(self, sample_rate): try: self.parent_ctrl_conn.send((self.Command.SET_SAMPLE_RATE.name, int(sample_rate))) except (BrokenPipeError, OSError): pass @property def channel_index(self) -> int: return self.__channel_index @channel_index.setter def channel_index(self, value: int): if value != self.__channel_index: self.__channel_index = value self.set_device_channel_index(value) def set_device_channel_index(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_CHANNEL_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def antenna_index(self): return self.__antenna_index @antenna_index.setter def antenna_index(self, value): if value != self.__antenna_index: self.__antenna_index = value self.set_device_antenna_index(value) def set_device_antenna_index(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_ANTENNA_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def freq_correction(self): return self.__freq_correction @freq_correction.setter def freq_correction(self, value): if value != self.__freq_correction: self.__freq_correction = value self.set_device_freq_correction(value) def set_device_freq_correction(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_FREQUENCY_CORRECTION.name, int(value))) except (BrokenPipeError, OSError): pass @property def direct_sampling_mode(self): return self.__direct_sampling_mode @direct_sampling_mode.setter def direct_sampling_mode(self, value): if value != self.__direct_sampling_mode: self.__direct_sampling_mode = value self.set_device_direct_sampling_mode(value) def set_device_direct_sampling_mode(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_DIRECT_SAMPLING_MODE.name, int(value))) except (BrokenPipeError, OSError): pass def start_rx_mode(self): self.init_recv_buffer() self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.is_receiving = True logger.info("{0}: Starting RX Mode".format(self.__class__.__name__)) self.receive_process = Process(target=self.receive_process_function, args=self.receive_process_arguments) self.receive_process.daemon = True self._start_read_rcv_buffer_thread() self._start_read_message_thread() try: self.receive_process.start() except OSError as e: logger.error(repr(e)) self.device_messages.append(repr(e)) def stop_rx_mode(self, msg): self.is_receiving = False 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 RX Mode: {1}".format(self.__class__.__name__, msg)) if hasattr(self, "receive_process") and self.receive_process.is_alive(): self.receive_process.join(0.5) if self.receive_process.is_alive(): logger.warning("{0}: Receive process is still alive, terminating it".format(self.__class__.__name__)) self.receive_process.terminate() self.receive_process.join() self.child_ctrl_conn.close() self.child_data_conn.close() self.parent_ctrl_conn.close() self.parent_data_conn.close() def start_tx_mode(self, samples_to_send: np.ndarray = None, repeats=None, resume=False): self.is_transmitting = True self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.init_send_parameters(samples_to_send, repeats, resume=resume) logger.info("{0}: Starting TX Mode".format(self.__class__.__name__)) self.transmit_process = Process(target=self.send_process_function, args=self.send_process_arguments) self.transmit_process.daemon = True self._start_read_message_thread() self.transmit_process.start() def stop_tx_mode(self, msg): self.is_transmitting = False 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(0.5) 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.child_ctrl_conn.close() self.parent_ctrl_conn.close() @staticmethod def unpack_complex(buffer, nvalues): pass @staticmethod def pack_complex(complex_samples: np.ndarray): pass def read_device_messages(self): while self.is_receiving or self.is_transmitting: try: message = self.parent_ctrl_conn.recv() try: action, return_code = message.split(":") self.log_retcode(int(return_code), action) except ValueError: self.device_messages.append("{0}: {1}".format(self.__class__.__name__, message)) time.sleep(0.1) except (EOFError, UnpicklingError, ConnectionResetError): break self.is_transmitting = False self.is_receiving = False logger.debug("Exiting read device errors thread") def read_receiving_queue(self): while self.is_receiving: try: byte_buffer = self.parent_data_conn.recv_bytes() n_samples = len(byte_buffer) // self.BYTES_PER_SAMPLE if n_samples > 0: if self.current_recv_index + n_samples >= len(self.receive_buffer): if self.resume_on_full_receive_buffer: self.current_recv_index = 0 if n_samples >= len(self.receive_buffer): n_samples = len(self.receive_buffer) - 1 else: self.stop_rx_mode( "Receiving buffer is full {0}/{1}".format(self.current_recv_index + n_samples, len(self.receive_buffer))) return end = n_samples * self.BYTES_PER_SAMPLE self.receive_buffer[self.current_recv_index:self.current_recv_index + n_samples] = \ self.unpack_complex(byte_buffer[:end], n_samples) old_index = self.current_recv_index self.current_recv_index += n_samples self.rcv_index_changed.emit(old_index, self.current_recv_index) except (BrokenPipeError, OSError): pass except EOFError: logger.info("EOF Error: Ending receive thread") break time.sleep(0.01) logger.debug("Exiting read_receive_queue thread.") def init_send_parameters(self, samples_to_send: np.ndarray = None, repeats: int = None, resume=False): if samples_to_send is not None: self.samples_to_send = samples_to_send self.send_buffer = None if self.send_buffer is None: self.send_buffer = self.pack_complex(self.samples_to_send) elif not resume: self.current_sending_repeat = 0 if repeats is not None: self.sending_repeats = repeats
class StreamProc(rogue.interfaces.stream.Slave): def __init__(self, stime, sevts, realTimeSim = False): # initialize interfaces rogue.interfaces.stream.Slave.__init__(self) # store the setting used to indicate that we are simulating waveforms self.realTimeSim = realTimeSim # Keep track of the dead time self.running_deadtime = 0 # Create locks and pipes self.lock = Lock() self.parent_conn, self.child_conn = Pipe() # pass the main running function to a separate thread self.processor = Process(target=sevts.run_subprocess, args=(self.lock, self.child_conn)) self.processor.start() # keep track of times self.t0 = time.time() # initial time for frame generation self.ft0 = stime def __del__(self): # rogue.interfaces.stream.Slave.__del__(self) def end(self): # send the command to end the execution self.parent_conn.send((True, None, 0)) self.parent_conn.close() self.processor.join() # rejoin the terminated tread self.processor.terminate() del self.processor def _acceptFrame(self,frame): cframe = bytearray(frame.getPayload()) frame.read(cframe,0) # #rdata = n.frombuffer(cframe, dtype=n.uint32, count=4, offset=len(cframe)-16) #fstarttime = (n.uint64(rdata[0]) << UINT64_VERSION_OF_32) + n.uint64(rdata[1]) #fendtime = (n.uint64(rdata[2]) << UINT64_VERSION_OF_32) + n.uint64(rdata[3]) # temporarily disable the frame start and end reading since they don't exist yet. fstarttime = n.uint64(0) fendtime = n.uint64(0) framelen = n.int64(fendtime)-fstarttime #print(self.running_deadtime, framelen) if self.realTimeSim: # enable real time distribution of waveforms fcurrenttime = (fendtime-self.ft0)/1e9 currenttime = (time.time()-self.t0) if currenttime < fcurrenttime: time.sleep(fcurrenttime-currenttime) #print('framelen', framelen) # add a frame to the streamer # make sure there is no data waiting to be picked up by the processor child_conn_stat = self.child_conn.poll() if not child_conn_stat: # pipe is empty. Check if the processor has the thread locked. If not, send the frame lockstatus = self.lock.acquire(block=False) # aquire lock if the processor isn't busy #print('loop lockstatus is', lockstatus, child_conn_stat) if lockstatus: # Send current frame to the processor along with the pre-frame dead time #print("Sending data") self.parent_conn.send((False, cframe, self.running_deadtime)) self.lock.release() # wait until the child process confirms that it got the data. This is needed for synchronization since the processor tends to be slower than the parent process hence the parent process might jump to the next frame before the processor is finished reading the current one. # I know that it's not great since it means that this process can hang if the processor takes too long but I couldn't think of a way to give the processor enough time to finish reading the data (before the parent process tries to send another frame) without putting an artifical sleep in the processor or the parent or making the processor use 100% of the cpu (stuck in a full speed while True loop) self.parent_conn.recv_bytes() # this was sent after the processor aquired a lock # reset the dead time self.running_deadtime = 0 else: self.running_deadtime += framelen else: self.running_deadtime += framelen
def main(which="PipedService"): print "main(): pid = {pid}, ppid = {ppid}".format(pid=os.getpid(), ppid=os.getppid()) if which == "PipedService": print "main(): Starting PipedService process..." pipeToProc, pipeToMain = Pipe() proc = PipedService(pipeToMain) proc.start() sleep(1) # [debug] wait a bit to flush out all messages from child processes proc.test() # [debug] test self and parent PIDs while proc.is_alive(): command = raw_input("main(): Command : ") if proc.is_alive(): pipeToProc.send_bytes(command) print "main(): Response: {0}".format(pipeToProc.recv_bytes()) else: print "main(): Oops! Process already died." print "main(): Done; joining on process(es)..." proc.join() elif which == "QueuedService": print "main(): Starting QueuedService child process..." service = QueuedService() service.start() print "main(): Starting cannedLoop() child process..." cannedCommands = ["Hi", "How", "is", "it going?", "quit"] pCannedLoop = Process(target=cannedLoop, args=(service, cannedCommands, 5)) pCannedLoop.start() print "main(): Starting interactiveLoop() (NOTE: Not a child process)..." interactiveLoop(service) print "main(): Joining on process(es)..." pCannedLoop.join() service.join() print "main(): Done." elif which == "MultiPipedService": print "main(): Starting MultiPipedService child process..." service = MultiPipedService() serviceHelper1 = service.addClient() serviceHelper2 = service.addClient() service.start() # NOTE must addClient()s before calling start() sleep(1) # let other process start-up messages to pass through print "main(): Starting cannedLoop() child process..." cannedCommands = ["Hi", "How", "is", "it going?", "quit"] pCannedLoop = Process(target=cannedLoop, args=(serviceHelper1, cannedCommands, 2)) pCannedLoop.start() sleep(1) # let other process start-up messages to pass through print "main(): Starting interactive loop..." while True: command = raw_input("Command > ") if not service.is_alive(): print "main(): Oops! Service already dead; aborting..." break response = serviceHelper2.runCommandSync(command) print "Response: {0}".format(response) if command == "quit": break print "main(): Interactive loop terminated." print "main(): Joining on process(es)..." pCannedLoop.join() service.join() # MultiPipedService automatically closes client connections on quit print "main(): Done." elif which == "SynchronizedService": print "main(): Starting SynchronizedService child process..." service = SynchronizedService() service.start() sleep(1) # let other process start-up messages to pass through print "main(): Starting cannedLoop() child process..." cannedCommands = ["Hi", "How", "is", "it going?", "quit"] pCannedLoop = Process(target=cannedLoop, args=(service, cannedCommands, 2)) pCannedLoop.start() sleep(1) # let other process start-up messages to pass through print "main(): Starting interactive loop..." while True: command = raw_input("Command > ") if not service.is_alive(): print "main(): Oops! Service already dead; aborting..." break response = service.runCommandSync(command) print "Response: {0}".format(response) if command == "quit": break print "main(): Interactive loop terminated." print "main(): Joining on process(es)..." pCannedLoop.join() service.join() # MultiPipedService automatically closes client connections on quit print "main(): Done." else: print "main(): Unknown service type \"{0}\"".format(which)
class Device(QObject): BYTES_PER_SAMPLE = None rcv_index_changed = pyqtSignal(int, int) def __init__(self, bw, freq, gain, srate, is_ringbuffer=False): super().__init__() self.error_not_open = -4242 self.__bandwidth = bw self.__frequency = freq self.__gain = gain self.__sample_rate = srate self.is_open = False self.bandwidth_is_adjustable = True self._max_bandwidth = 1 self._max_frequency = 1 self._max_sample_rate = 1 self._max_gain = 1 self.success = 0 self.error_codes = {} self.errors = set() self.parent_conn, self.child_conn = Pipe() self.send_buffer = None self.send_buffer_reader = None self.samples_to_send = np.array([], dtype=np.complex64) self.sending_repeats = 1 # How often shall the sending sequence be repeated? -1 = forever self.current_sending_repeat = 0 self.is_ringbuffer = is_ringbuffer # Ringbuffer for Spectrum Analyzer or Protocol Sniffing self.current_recv_index = 0 self.current_sent_sample = 0 self.is_receiving = False self.is_transmitting = False self.device_ip = "192.168.10.2" # For USRP self.receive_buffer = None self.spectrum_x = None self.spectrum_y = None def _start_sendbuffer_thread(self): self.sendbuffer_thread = threading.Thread( target=self.check_send_buffer) self.sendbuffer_thread.daemon = True self.sendbuffer_thread.start() def _start_read_rcv_buffer_thread(self): self.read_recv_buffer_thread = threading.Thread( target=self.read_receiving_queue) self.read_recv_buffer_thread.daemon = True self.read_recv_buffer_thread.start() def init_recv_buffer(self): if self.receive_buffer is None: if self.is_ringbuffer: nsamples = 10**5 else: # Take 60% of avail memory nsamples = 0.6 * (psutil.virtual_memory().free / 8) self.receive_buffer = np.zeros(int(nsamples), dtype=np.complex64, order='C') logger.info( "Initialized receiving buffer with size {0:.2f}MB".format( self.receive_buffer.nbytes / (1024 * 1024))) def log_retcode(self, retcode: int, action: str, msg=""): msg = str(msg) error_code_msg = self.error_codes[ retcode] if retcode in self.error_codes else "Error Code: " + str( retcode) if retcode == self.success: if msg: logger.info("{0}-{1} ({2}): Success".format( type(self).__name__, action, msg)) else: logger.info("{0}-{1}: Success".format( type(self).__name__, action)) else: if msg: err = "{0}-{1} ({4}): {2} ({3})".format( type(self).__name__, action, error_code_msg, retcode, msg) else: err = "{0}-{1}: {2} ({3})".format( type(self).__name__, action, error_code_msg, retcode) self.errors.add(err) logger.error(err) @property def received_data(self): return self.receive_buffer[:self.current_recv_index] @property def sent_data(self): return self.samples_to_send[:self.current_sent_sample] @property def sending_finished(self): # current_sent_sample is only set in method check_send_buffer return self.current_sent_sample == len(self.samples_to_send) @property def bandwidth(self): return self.__bandwidth @bandwidth.setter def bandwidth(self, value): if not self.bandwidth_is_adjustable: return 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) @abstractmethod def set_device_bandwidth(self, bandwidth): pass @property def frequency(self): return self.__frequency @frequency.setter 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 if self.is_open: self.set_device_frequency(value) @abstractmethod def set_device_frequency(self, frequency): pass @property def gain(self): return self.__gain @gain.setter 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) @abstractmethod def set_device_gain(self, gain): pass @property def sample_rate(self): return self.__sample_rate @sample_rate.setter 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 if self.is_open: self.set_device_sample_rate(value) @abstractmethod def set_device_sample_rate(self, sample_rate): pass @abstractmethod def open(self): pass @abstractmethod def close(self): pass @abstractmethod def start_rx_mode(self): pass @abstractmethod def stop_rx_mode(self, msg): pass @abstractmethod def start_tx_mode(self, samples_to_send: np.ndarray = None, repeats=None, resume=False): pass @abstractmethod def stop_tx_mode(self, msg): pass @staticmethod def unpack_complex(buffer, nvalues): pass @staticmethod def pack_complex(complex_samples: np.ndarray): pass def set_device_parameters(self): self.set_device_bandwidth(self.bandwidth) self.set_device_frequency(self.frequency) self.set_device_gain(self.gain) self.set_device_sample_rate(self.sample_rate) def read_receiving_queue(self): while self.is_receiving: try: byte_buffer = self.parent_conn.recv_bytes() 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 except EOFError: logger.info("EOF Error: Ending receive thread") break time.sleep(0.01) def init_send_parameters(self, samples_to_send: np.ndarray = None, repeats: int = None, skip_device_parameters=False, resume=False): if not skip_device_parameters: self.set_device_parameters() if samples_to_send is not None: try: self.send_buffer_reader.close() self.send_buffer.close() except AttributeError: pass self.samples_to_send = samples_to_send if self.send_buffer is None or self.send_buffer.closed: self.send_buffer = io.BytesIO( self.pack_complex(self.samples_to_send)) self.send_buffer_reader = io.BufferedReader(self.send_buffer) elif not resume: self.reset_send_buffer() self.current_sending_repeat = 0 if repeats is not None: self.sending_repeats = repeats def reset_send_buffer(self): try: self.send_buffer_reader.seek(0) self.current_sent_sample = 0 except ValueError: logger.info("Send buffer was already closed. Cant reset it.") def check_send_buffer(self): def sending_iteration_remaining(current_sending_repeat: int, sending_repeats: int): return current_sending_repeat < sending_repeats or sending_repeats == -1 # sending_repeats -1 = forever assert len(self.samples_to_send) == len( self.send_buffer_reader.read()) // self.BYTES_PER_SAMPLE self.send_buffer.seek(self.current_sent_sample * self.BYTES_PER_SAMPLE) while sending_iteration_remaining( self.current_sending_repeat, self.sending_repeats) and self.is_transmitting: while self.is_transmitting and self.send_buffer_reader.peek(): try: self.current_sent_sample = self.send_buffer_reader.tell( ) // self.BYTES_PER_SAMPLE except ValueError: # I/O operation on closed file. --> Buffer was closed break time.sleep(0.01) self.current_sending_repeat += 1 if sending_iteration_remaining(self.current_sending_repeat, self.sending_repeats): self.reset_send_buffer() if self.current_sent_sample >= len(self.samples_to_send) - 1: self.current_sent_sample = len( self.samples_to_send) # Mark transmission as finished else: logger.info("Skipped {0:d} samples in sending".format( len(self.samples_to_send) - self.current_sent_sample)) def callback_recv(self, buffer): try: self.child_conn.send_bytes(buffer) except BrokenPipeError: pass return 0 def callback_send(self, buffer_length): try: return self.send_buffer_reader.read(buffer_length) except BrokenPipeError: return b"" except ValueError: logger.info( "Receiving Thread was closed. Callback cant read queue.") return b""
class Device(QObject): JOIN_TIMEOUT = 1.0 SYNC_TX_CHUNK_SIZE = 0 CONTINUOUS_TX_CHUNK_SIZE = 0 class Command(Enum): STOP = 0 SET_FREQUENCY = 1 SET_SAMPLE_RATE = 2 SET_BANDWIDTH = 3 SET_RF_GAIN = 4 SET_IF_GAIN = 5 SET_BB_GAIN = 6 SET_DIRECT_SAMPLING_MODE = 7 SET_FREQUENCY_CORRECTION = 8 SET_CHANNEL_INDEX = 9 SET_ANTENNA_INDEX = 10 data_received = pyqtSignal(np.ndarray) ASYNCHRONOUS = False DEVICE_LIB = None DEVICE_METHODS = { Command.SET_FREQUENCY.name: "set_center_freq", Command.SET_SAMPLE_RATE.name: "set_sample_rate", Command.SET_BANDWIDTH.name: "set_bandwidth", Command.SET_RF_GAIN.name: "set_rf_gain", Command.SET_IF_GAIN.name: {"rx": "set_if_rx_gain", "tx": "set_if_tx_gain"}, Command.SET_BB_GAIN.name: {"rx": "set_baseband_gain"} } @classmethod def get_device_list(cls): return [] @classmethod 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)) @classmethod def setup_device(cls, ctrl_connection: Connection, device_identifier): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def init_device(cls, ctrl_connection: Connection, is_tx: bool, parameters: OrderedDict) -> bool: if cls.setup_device(ctrl_connection, device_identifier=parameters["identifier"]): for parameter, value in parameters.items(): cls.process_command((parameter, value), ctrl_connection, is_tx) return True else: return False @classmethod def adapt_num_read_samples_to_sample_rate(cls, sample_rate: float): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def shutdown_device(cls, ctrl_connection, is_tx: bool): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_receive_mode(cls, data_connection: Connection, ctrl_connection: Connection) -> int: raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_receive(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def receive_sync(cls, data_conn: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_send_mode(cls, callback: object): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_send(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def send_sync(cls, data): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def device_receive(cls, data_connection: Connection, ctrl_connection: Connection, dev_parameters: OrderedDict): if not cls.init_device(ctrl_connection, is_tx=False, parameters=dev_parameters): ctrl_connection.send("failed to start rx mode") return False try: cls.adapt_num_read_samples_to_sample_rate(dev_parameters[cls.Command.SET_SAMPLE_RATE.name]) except NotImplementedError: # Many SDRs like HackRF or AirSpy do not need to calculate SYNC_RX_CHUNK_SIZE # as default values are either fine or given by the hardware pass if cls.ASYNCHRONOUS: ret = cls.enter_async_receive_mode(data_connection, ctrl_connection) else: ret = cls.prepare_sync_receive(ctrl_connection) if ret != 0: ctrl_connection.send("failed to start rx mode") return False exit_requested = False ctrl_connection.send("successfully started rx mode") while not exit_requested: if cls.ASYNCHRONOUS: time.sleep(0.25) else: cls.receive_sync(data_connection) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=False) if result == cls.Command.STOP.name: exit_requested = True break cls.shutdown_device(ctrl_connection, is_tx=False) data_connection.close() ctrl_connection.close() @classmethod 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: 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 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, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseband_gain=1, resume_on_full_receive_buffer=False): super().__init__() self.error_not_open = -4242 self.__bandwidth = bandwidth self.__frequency = center_freq self.__gain = gain # = rf_gain self.__if_gain = if_gain self.__baseband_gain = baseband_gain self.__sample_rate = sample_rate self.__channel_index = 0 self.__antenna_index = 0 self.__freq_correction = 0 self.__direct_sampling_mode = 0 self.bandwidth_is_adjustable = True self.is_in_spectrum_mode = False self.sending_is_continuous = False self.continuous_send_ring_buffer = None self.num_samples_to_send = None # None = get automatically. This value needs to be known in continuous send mode self._current_sent_sample = Value("L", 0) self._current_sending_repeat = Value("L", 0) self.success = 0 self.error_codes = {} self.device_messages = [] self.receive_process_function = self.device_receive self.send_process_function = self.device_send self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.send_buffer = None self.send_buffer_reader = None self.device_serial = None self.device_number = 0 self.emit_data_received_signal = False # used for protocol sniffer self.samples_to_send = np.array([], dtype=np.complex64) self.sending_repeats = 1 # How often shall the sending sequence be repeated? 0 = forever self.resume_on_full_receive_buffer = resume_on_full_receive_buffer # for Spectrum Analyzer or Protocol Sniffing self.current_recv_index = 0 self.is_receiving = False self.is_transmitting = False self.device_ip = "192.168.10.2" # For USRP and RTLSDRTCP self.receive_buffer = None self.spectrum_x = None self.spectrum_y = None def _start_read_rcv_buffer_thread(self): self.read_recv_buffer_thread = threading.Thread(target=self.read_receiving_queue) self.read_recv_buffer_thread.daemon = True self.read_recv_buffer_thread.start() def _start_read_message_thread(self): self.read_dev_msg_thread = threading.Thread(target=self.read_device_messages) self.read_dev_msg_thread.daemon = True self.read_dev_msg_thread.start() @property def has_multi_device_support(self): return False @property def current_sent_sample(self): return self._current_sent_sample.value // 2 @current_sent_sample.setter def current_sent_sample(self, value: int): self._current_sent_sample.value = value * 2 @property def current_sending_repeat(self): return self._current_sending_repeat.value @current_sending_repeat.setter def current_sending_repeat(self, value: int): self._current_sending_repeat.value = value @property def device_parameters(self) -> OrderedDict: return OrderedDict([(self.Command.SET_FREQUENCY.name, self.frequency), (self.Command.SET_SAMPLE_RATE.name, self.sample_rate), (self.Command.SET_BANDWIDTH.name, self.bandwidth), (self.Command.SET_RF_GAIN.name, self.gain), (self.Command.SET_IF_GAIN.name, self.if_gain), (self.Command.SET_BB_GAIN.name, self.baseband_gain), ("identifier", self.device_serial)]) @property def send_config(self) -> SendConfig: if self.num_samples_to_send is None: total_samples = len(self.send_buffer) else: total_samples = 2 * self.num_samples_to_send return SendConfig(self.send_buffer, self._current_sent_sample, self._current_sending_repeat, total_samples, self.sending_repeats, continuous=self.sending_is_continuous, pack_complex_method=self.pack_complex, continuous_send_ring_buffer=self.continuous_send_ring_buffer) @property def receive_process_arguments(self): return self.child_data_conn, self.child_ctrl_conn, self.device_parameters @property def send_process_arguments(self): return self.child_ctrl_conn, self.send_config, self.device_parameters def init_recv_buffer(self): if self.receive_buffer is None: num_samples = SettingsProxy.get_receive_buffer_size(self.resume_on_full_receive_buffer, self.is_in_spectrum_mode) self.receive_buffer = np.zeros(int(num_samples), dtype=np.complex64, order='C') def log_retcode(self, retcode: int, action: str, msg=""): msg = str(msg) error_code_msg = self.error_codes[retcode] if retcode in self.error_codes else "Error Code: " + str(retcode) if retcode == self.success: if msg: formatted_message = "{0}-{1} ({2}): Success".format(type(self).__name__, action, msg) else: formatted_message = "{0}-{1}: Success".format(type(self).__name__, action) logger.info(formatted_message) else: if msg: formatted_message = "{0}-{1} ({4}): {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode, msg) else: formatted_message = "{0}-{1}: {2} ({3})".format(type(self).__name__, action, error_code_msg, retcode) logger.error(formatted_message) self.device_messages.append(formatted_message) @property def received_data(self): return self.receive_buffer[:self.current_recv_index] @property def sent_data(self): return self.samples_to_send[:self.current_sent_sample] @property def sending_finished(self): return self.current_sent_sample == len(self.samples_to_send) @property def bandwidth(self): return self.__bandwidth @bandwidth.setter def bandwidth(self, value): if not self.bandwidth_is_adjustable: return if value != self.__bandwidth: self.__bandwidth = value self.set_device_bandwidth(value) def set_device_bandwidth(self, bw): try: self.parent_ctrl_conn.send((self.Command.SET_BANDWIDTH.name, int(bw))) except (BrokenPipeError, OSError): pass @property def frequency(self): return self.__frequency @frequency.setter def frequency(self, value): if value != self.__frequency: self.__frequency = value self.set_device_frequency(value) def set_device_frequency(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_FREQUENCY.name, int(value))) except (BrokenPipeError, OSError): pass @property def gain(self): return self.__gain @gain.setter def gain(self, value): if value != self.__gain: self.__gain = value self.set_device_gain(value) def set_device_gain(self, gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_RF_GAIN.name, gain)) except (BrokenPipeError, OSError): pass @property def if_gain(self): return self.__if_gain @if_gain.setter def if_gain(self, value): if value != self.__if_gain: self.__if_gain = value self.set_device_if_gain(value) def set_device_if_gain(self, if_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_IF_GAIN.name, if_gain)) except (BrokenPipeError, OSError): pass @property def baseband_gain(self): return self.__baseband_gain @baseband_gain.setter def baseband_gain(self, value): if value != self.__baseband_gain: self.__baseband_gain = value self.set_device_baseband_gain(value) def set_device_baseband_gain(self, baseband_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_BB_GAIN.name, baseband_gain)) except (BrokenPipeError, OSError): pass @property def sample_rate(self): return self.__sample_rate @sample_rate.setter def sample_rate(self, value): if value != self.__sample_rate: self.__sample_rate = value self.set_device_sample_rate(value) def set_device_sample_rate(self, sample_rate): try: self.parent_ctrl_conn.send((self.Command.SET_SAMPLE_RATE.name, int(sample_rate))) except (BrokenPipeError, OSError): pass @property def channel_index(self) -> int: return self.__channel_index @channel_index.setter def channel_index(self, value: int): if value != self.__channel_index: self.__channel_index = value self.set_device_channel_index(value) def set_device_channel_index(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_CHANNEL_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def antenna_index(self): return self.__antenna_index @antenna_index.setter def antenna_index(self, value): if value != self.__antenna_index: self.__antenna_index = value self.set_device_antenna_index(value) def set_device_antenna_index(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_ANTENNA_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def freq_correction(self): return self.__freq_correction @freq_correction.setter def freq_correction(self, value): if value != self.__freq_correction: self.__freq_correction = value self.set_device_freq_correction(value) def set_device_freq_correction(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_FREQUENCY_CORRECTION.name, int(value))) except (BrokenPipeError, OSError): pass @property def direct_sampling_mode(self): return self.__direct_sampling_mode @direct_sampling_mode.setter def direct_sampling_mode(self, value): if value != self.__direct_sampling_mode: self.__direct_sampling_mode = value self.set_device_direct_sampling_mode(value) def set_device_direct_sampling_mode(self, value): try: self.parent_ctrl_conn.send((self.Command.SET_DIRECT_SAMPLING_MODE.name, int(value))) except (BrokenPipeError, OSError): pass def start_rx_mode(self): self.init_recv_buffer() self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.is_receiving = True logger.info("{0}: Starting RX Mode".format(self.__class__.__name__)) self.receive_process = Process(target=self.receive_process_function, args=self.receive_process_arguments) self.receive_process.daemon = True self._start_read_rcv_buffer_thread() self._start_read_message_thread() try: self.receive_process.start() except OSError as e: logger.error(repr(e)) self.device_messages.append(repr(e)) def stop_rx_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 RX Mode: {1}".format(self.__class__.__name__, msg)) if hasattr(self, "receive_process") and self.receive_process.is_alive(): self.receive_process.join(self.JOIN_TIMEOUT) if self.receive_process.is_alive(): logger.warning("{0}: Receive process is still alive, terminating it".format(self.__class__.__name__)) self.receive_process.terminate() self.receive_process.join() self.is_receiving = False for connection in (self.parent_ctrl_conn, self.parent_data_conn, self.child_ctrl_conn, self.child_data_conn): try: connection.close() except OSError as e: logger.exception(e) def start_tx_mode(self, samples_to_send: np.ndarray = None, repeats=None, resume=False): self.is_transmitting = True self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.init_send_parameters(samples_to_send, repeats, resume=resume) logger.info("{0}: Starting TX Mode".format(self.__class__.__name__)) self.transmit_process = Process(target=self.send_process_function, args=self.send_process_arguments) self.transmit_process.daemon = True self._start_read_message_thread() self.transmit_process.start() 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) @staticmethod def unpack_complex(buffer): pass @staticmethod def pack_complex(complex_samples: np.ndarray): pass def read_device_messages(self): while self.is_receiving or self.is_transmitting: try: message = self.parent_ctrl_conn.recv() try: splitted = message.split(":") action = ":".join(splitted[:-1]) return_code = splitted[-1] self.log_retcode(int(return_code), action) except ValueError: self.device_messages.append("{0}: {1}".format(self.__class__.__name__, message)) except (EOFError, UnpicklingError, OSError, ConnectionResetError) as e: logger.info("Exiting read device message thread due to " + str(e)) break self.is_transmitting = False self.is_receiving = False logger.debug("Exiting read device errors thread") def read_receiving_queue(self): while self.is_receiving: try: byte_buffer = self.parent_data_conn.recv_bytes() samples = self.unpack_complex(byte_buffer) n_samples = len(samples) if n_samples == 0: continue except OSError as e: logger.exception(e) continue except EOFError: logger.info("EOF Error: Ending receive thread") break if self.current_recv_index + n_samples >= len(self.receive_buffer): if self.resume_on_full_receive_buffer: self.current_recv_index = 0 if n_samples >= len(self.receive_buffer): n_samples = len(self.receive_buffer) - 1 else: self.stop_rx_mode( "Receiving buffer is full {0}/{1}".format(self.current_recv_index + n_samples, len(self.receive_buffer))) return self.receive_buffer[self.current_recv_index:self.current_recv_index + n_samples] = samples[:n_samples] self.current_recv_index += n_samples if self.emit_data_received_signal: self.data_received.emit(samples) logger.debug("Exiting read_receive_queue thread.") def init_send_parameters(self, samples_to_send: np.ndarray = None, repeats: int = None, resume=False): if samples_to_send is not None: self.samples_to_send = samples_to_send self.send_buffer = None if self.send_buffer is None: self.send_buffer = self.pack_complex(self.samples_to_send) elif not resume: self.current_sending_repeat = 0 if repeats is not None: self.sending_repeats = repeats
def test_cython_wrapper(self): print("Devices:", limesdr.get_device_list()) # print("Open:", limesdr.open("LimeSDR-USB, media=USB 3.0, module=STREAM, addr=1d50:6108, serial=0009060B0049180A")) print("Open:", limesdr.open()) print("-" * 20) print("Is Open 0:", limesdr.is_open(0)) print("Is Open 1:", limesdr.is_open(1)) print("Init", limesdr.init()) limesdr.set_tx(True) self.assertTrue(limesdr.get_tx()) #print(limesdr.IS_TX) print("Num Channels TX:", limesdr.get_num_channels()) print("TX antennas", limesdr.get_antenna_list()) limesdr.set_tx(False) self.assertFalse(limesdr.get_tx()) print("Num Channels RX:", limesdr.get_num_channels()) limesdr.CHANNEL = 0 print("Enable RX Channel 0:", limesdr.enable_channel(True, False, 0)) #path = os.path.realpath(os.path.join(__file__, "..", "..", "src", "urh", "dev", "native", "lime.ini")) #print(path) #limesdr.load_config(path) #limesdr.save_config("/tmp/lime_test.ini") clocks = ["LMS_CLOCK_REF", "LMS_CLOCK_SXR", "LMS_CLOCK_SXT", "LMS_CLOCK_CGEN", "LMS_CLOCK_RXTSP", "LMS_CLOCK_TXTSP"] for i, clock in enumerate(clocks): print(clock, limesdr.get_clock_freq(i)) limesdr.print_last_error() print("RX Sample Rate Range:", limesdr.get_sample_rate_range()) print("RX Channel 0 Sample Rate:", limesdr.get_sample_rate()) print("Set Sample Rate:", limesdr.set_sample_rate(2e6)) print("RX Channel 0 Sample Rate:", limesdr.get_sample_rate()) limesdr.print_last_error() print("RX Frequency Range:", limesdr.get_center_frequency_range()) print("RX 0 center freq:", limesdr.get_center_frequency()) print("RX 0 set center freq:", limesdr.set_center_frequency(433.92e6)) print("RX 0 center freq:", limesdr.get_center_frequency()) limesdr.print_last_error() print("RX 0 gain", limesdr.get_normalized_gain()) print("RX 0 set gain", limesdr.set_normalized_gain(0.5)) print("RX 0 gain", limesdr.get_normalized_gain()) limesdr.print_last_error() print("RX Bandwidth Range", limesdr.get_lpf_bandwidth_range()) print("RX 0 Bandwidth", limesdr.get_lpf_bandwidth()) print("RX 0 set Bandwidth", limesdr.set_lpf_bandwidth(20e6)) print("RX 0 Bandwidth", limesdr.get_lpf_bandwidth()) limesdr.print_last_error() print("RX 0 calibrate:", limesdr.calibrate(20e6)) limesdr.print_last_error() antenna_list = limesdr.get_antenna_list() print("RX 0 antenna list", antenna_list) print("RX 0 current antenna", limesdr.get_antenna(), antenna_list[limesdr.get_antenna()]) print("RX 0 current antenna BW", limesdr.get_antenna_bw(limesdr.get_antenna())) print("Chip Temperature", limesdr.get_chip_temperature()) parent_conn, child_conn = Pipe() for _ in range(2): limesdr.print_last_error() print("Setup stream", limesdr.setup_stream(1000)) print("Start stream", limesdr.start_stream()) limesdr.recv_stream(child_conn, 1000, 100) print("Stop stream", limesdr.stop_stream()) print("Destroy stream", limesdr.destroy_stream()) print(parent_conn.recv_bytes()) limesdr.set_tx(True) self.assertTrue(limesdr.get_tx()) samples_to_send = np.ones(32768, dtype=np.complex64) for _ in range(2): limesdr.print_last_error() print("Setup stream", limesdr.setup_stream(4000000000)) print("Start stream", limesdr.start_stream()) print("Send samples", limesdr.send_stream(samples_to_send, 100)) print("Stop stream", limesdr.stop_stream()) print("Destroy stream", limesdr.destroy_stream()) print("-" * 20) print("Close:", limesdr.close()) print("Is Open 0:", limesdr.is_open(0)) print("Is Open 1:", limesdr.is_open(1))
from multiprocessing import Pipe a, b = Pipe() a.send([1, 'hello', None]) print(b.recv()) b.send_bytes(b'thank you') print(a.recv_bytes()) import array arr1 = array.array('i', range(5)) arr2 = array.array('i', [0] * 10) a.send_bytes(arr1) count = b.recv_bytes_into(arr2) assert count == len(arr1) * arr1.itemsize print(arr2)
parent_conn, child_conn = Pipe() fpcap = open("./tmp.pcap", 'wb') fwrite = Writer(fpcap) def multi_process(conn): print("start") sock = rxRawSocket("vboxnet0") tmp = sock.rx_packets(conn) next(tmp) p = Process(target=multi_process, args=(child_conn, )) p.start() num = 0 while True: one = parent_conn.recv_bytes() fwrite.writepkt(one) num += 1 print("num: ", num) sock = rxRawSocket("vboxnet0") i = 0 # getPack = sock.rx_packets() for packet in sock.rx_packets(None): fwrite.writepkt(packet) i += 1 print("num: %d" % i)
class Device(object): JOIN_TIMEOUT = 1.0 SYNC_TX_CHUNK_SIZE = 0 CONTINUOUS_TX_CHUNK_SIZE = 0 DATA_TYPE = np.float32 class Command(Enum): STOP = 0 SET_FREQUENCY = 1 SET_SAMPLE_RATE = 2 SET_BANDWIDTH = 3 SET_RF_GAIN = 4 SET_IF_GAIN = 5 SET_BB_GAIN = 6 SET_DIRECT_SAMPLING_MODE = 7 SET_FREQUENCY_CORRECTION = 8 SET_CHANNEL_INDEX = 9 SET_ANTENNA_INDEX = 10 ASYNCHRONOUS = False DEVICE_LIB = None DEVICE_METHODS = { Command.SET_FREQUENCY.name: "set_center_freq", Command.SET_SAMPLE_RATE.name: "set_sample_rate", Command.SET_BANDWIDTH.name: "set_bandwidth", Command.SET_RF_GAIN.name: "set_rf_gain", Command.SET_IF_GAIN.name: { "rx": "set_if_rx_gain", "tx": "set_if_tx_gain" }, Command.SET_BB_GAIN.name: { "rx": "set_baseband_gain" } } @classmethod def get_device_list(cls): return [] @classmethod 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)) @classmethod def setup_device(cls, ctrl_connection: Connection, device_identifier): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def init_device(cls, ctrl_connection: Connection, is_tx: bool, parameters: OrderedDict) -> bool: if cls.setup_device(ctrl_connection, device_identifier=parameters["identifier"]): for parameter, value in parameters.items(): cls.process_command((parameter, value), ctrl_connection, is_tx) return True else: return False @classmethod def adapt_num_read_samples_to_sample_rate(cls, sample_rate: float): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def shutdown_device(cls, ctrl_connection, is_tx: bool): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_receive_mode(cls, data_connection: Connection, ctrl_connection: Connection) -> int: raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_receive(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def receive_sync(cls, data_conn: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def enter_async_send_mode(cls, callback: object): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def prepare_sync_send(cls, ctrl_connection: Connection): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def send_sync(cls, data): raise NotImplementedError("Overwrite this method in subclass!") @classmethod def device_receive(cls, data_connection: Connection, ctrl_connection: Connection, dev_parameters: OrderedDict): if not cls.init_device( ctrl_connection, is_tx=False, parameters=dev_parameters): ctrl_connection.send("failed to start rx mode") return False try: cls.adapt_num_read_samples_to_sample_rate( dev_parameters[cls.Command.SET_SAMPLE_RATE.name]) except NotImplementedError: # Many SDRs like HackRF or AirSpy do not need to calculate SYNC_RX_CHUNK_SIZE # as default values are either fine or given by the hardware pass if cls.ASYNCHRONOUS: ret = cls.enter_async_receive_mode(data_connection, ctrl_connection) else: ret = cls.prepare_sync_receive(ctrl_connection) if ret != 0: ctrl_connection.send("failed to start rx mode") return False exit_requested = False ctrl_connection.send("successfully started rx mode") while not exit_requested: if cls.ASYNCHRONOUS: try: time.sleep(0.25) except KeyboardInterrupt: pass else: cls.receive_sync(data_connection) while ctrl_connection.poll(): result = cls.process_command(ctrl_connection.recv(), ctrl_connection, is_tx=False) if result == cls.Command.STOP.name: exit_requested = True break cls.shutdown_device(ctrl_connection, is_tx=False) data_connection.close() ctrl_connection.close() @classmethod 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, center_freq, sample_rate, bandwidth, gain, if_gain=1, baseband_gain=1, resume_on_full_receive_buffer=False): super().__init__() self.error_not_open = -4242 self.__bandwidth = bandwidth self.__frequency = center_freq self.__gain = gain # = rf_gain self.__if_gain = if_gain self.__baseband_gain = baseband_gain self.__sample_rate = sample_rate self.__channel_index = 0 self.__antenna_index = 0 self.__freq_correction = 0 self.__direct_sampling_mode = 0 self.bandwidth_is_adjustable = True self.is_in_spectrum_mode = False self.sending_is_continuous = False self.continuous_send_ring_buffer = None self.num_samples_to_send = None # None = get automatically. This value needs to be known in continuous send mode self._current_sent_sample = Value("L", 0) self._current_sending_repeat = Value("L", 0) self.success = 0 self.error_codes = {} self.device_messages = [] self.receive_process_function = self.device_receive self.send_process_function = self.device_send self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.send_buffer = None self.send_buffer_reader = None self.device_serial = None self.device_number = 0 self.samples_to_send = np.array([], dtype=self.DATA_TYPE) self.sending_repeats = 1 # How often shall the sending sequence be repeated? 0 = forever self.resume_on_full_receive_buffer = resume_on_full_receive_buffer # for Spectrum Analyzer or Protocol Sniffing self.current_recv_index = 0 self.is_receiving = False self.is_transmitting = False self.device_ip = "192.168.10.2" # For USRP and RTLSDRTCP self.receive_buffer = None self.my_receive_buffer = None self.my_acess_record_iq = False self.spectrum_x = None self.spectrum_y = None self.apply_dc_correction = False def _start_read_rcv_buffer_thread(self): self.read_recv_buffer_thread = threading.Thread( target=self.read_receiving_queue) self.read_recv_buffer_thread.daemon = True self.read_recv_buffer_thread.start() def _start_read_message_thread(self): self.read_dev_msg_thread = threading.Thread( target=self.read_device_messages) self.read_dev_msg_thread.daemon = True self.read_dev_msg_thread.start() @property def has_multi_device_support(self): return False @property def current_sent_sample(self): return self._current_sent_sample.value // 2 @current_sent_sample.setter def current_sent_sample(self, value: int): self._current_sent_sample.value = value * 2 @property def current_sending_repeat(self): return self._current_sending_repeat.value @current_sending_repeat.setter def current_sending_repeat(self, value: int): self._current_sending_repeat.value = value @property def device_parameters(self) -> OrderedDict: return OrderedDict([ (self.Command.SET_FREQUENCY.name, self.frequency), (self.Command.SET_SAMPLE_RATE.name, self.sample_rate), (self.Command.SET_BANDWIDTH.name, self.bandwidth), (self.Command.SET_RF_GAIN.name, self.gain), (self.Command.SET_IF_GAIN.name, self.if_gain), (self.Command.SET_BB_GAIN.name, self.baseband_gain), ("identifier", self.device_serial) ]) @property def send_config(self) -> SendConfig: if self.num_samples_to_send is None: total_samples = len(self.send_buffer) else: total_samples = 2 * self.num_samples_to_send return SendConfig( self.send_buffer, self._current_sent_sample, self._current_sending_repeat, total_samples, self.sending_repeats, continuous=self.sending_is_continuous, iq_to_bytes_method=self.iq_to_bytes, continuous_send_ring_buffer=self.continuous_send_ring_buffer) @property def receive_process_arguments(self): return self.child_data_conn, self.child_ctrl_conn, self.device_parameters @property def send_process_arguments(self): return self.child_ctrl_conn, self.send_config, self.device_parameters def init_recv_buffer(self): if self.receive_buffer is None: num_samples = SettingsProxy.get_receive_buffer_size( self.resume_on_full_receive_buffer, self.is_in_spectrum_mode) self.receive_buffer = IQArray(None, dtype=self.DATA_TYPE, n=int(num_samples)) def log_retcode(self, retcode: int, action: str, msg=""): msg = str(msg) error_code_msg = self.error_codes[ retcode] if retcode in self.error_codes else "Error Code: " + str( retcode) if retcode == self.success: if msg: formatted_message = "{0}-{1} ({2}): Success".format( type(self).__name__, action, msg) else: formatted_message = "{0}-{1}: Success".format( type(self).__name__, action) logger.info(formatted_message) else: if msg: formatted_message = "{0}-{1} ({4}): {2} ({3})".format( type(self).__name__, action, error_code_msg, retcode, msg) else: formatted_message = "{0}-{1}: {2} ({3})".format( type(self).__name__, action, error_code_msg, retcode) logger.error(formatted_message) self.device_messages.append(formatted_message) @property def received_data(self): return self.receive_buffer[:self.current_recv_index] @property def sent_data(self): return self.samples_to_send[:self.current_sent_sample] @property def sending_finished(self): return self.current_sent_sample == len(self.samples_to_send) @property def bandwidth(self): return self.__bandwidth @bandwidth.setter def bandwidth(self, value): if not self.bandwidth_is_adjustable: return if value != self.__bandwidth: self.__bandwidth = value self.set_device_bandwidth(value) def set_device_bandwidth(self, bw): try: self.parent_ctrl_conn.send( (self.Command.SET_BANDWIDTH.name, int(bw))) except (BrokenPipeError, OSError): pass @property def frequency(self): return self.__frequency @frequency.setter def frequency(self, value): if value != self.__frequency: self.__frequency = value self.set_device_frequency(value) def set_device_frequency(self, value): try: self.parent_ctrl_conn.send( (self.Command.SET_FREQUENCY.name, int(value))) except (BrokenPipeError, OSError): pass @property def gain(self): return self.__gain @gain.setter def gain(self, value): if value != self.__gain: self.__gain = value self.set_device_gain(value) def set_device_gain(self, gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send((self.Command.SET_RF_GAIN.name, gain)) except (BrokenPipeError, OSError): pass @property def if_gain(self): return self.__if_gain @if_gain.setter def if_gain(self, value): if value != self.__if_gain: self.__if_gain = value self.set_device_if_gain(value) def set_device_if_gain(self, if_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send( (self.Command.SET_IF_GAIN.name, if_gain)) except (BrokenPipeError, OSError): pass @property def baseband_gain(self): return self.__baseband_gain @baseband_gain.setter def baseband_gain(self, value): if value != self.__baseband_gain: self.__baseband_gain = value self.set_device_baseband_gain(value) def set_device_baseband_gain(self, baseband_gain): try: # Do not cast gain to int here, as it may be float e.g. for normalized USRP gain or LimeSDR gain self.parent_ctrl_conn.send( (self.Command.SET_BB_GAIN.name, baseband_gain)) except (BrokenPipeError, OSError): pass @property def sample_rate(self): return self.__sample_rate @sample_rate.setter def sample_rate(self, value): if value != self.__sample_rate: self.__sample_rate = value self.set_device_sample_rate(value) def set_device_sample_rate(self, sample_rate): try: self.parent_ctrl_conn.send( (self.Command.SET_SAMPLE_RATE.name, int(sample_rate))) except (BrokenPipeError, OSError): pass @property def channel_index(self) -> int: return self.__channel_index @channel_index.setter def channel_index(self, value: int): if value != self.__channel_index: self.__channel_index = value self.set_device_channel_index(value) def set_device_channel_index(self, value): try: self.parent_ctrl_conn.send( (self.Command.SET_CHANNEL_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def antenna_index(self): return self.__antenna_index @antenna_index.setter def antenna_index(self, value): if value != self.__antenna_index: self.__antenna_index = value self.set_device_antenna_index(value) def set_device_antenna_index(self, value): try: self.parent_ctrl_conn.send( (self.Command.SET_ANTENNA_INDEX.name, int(value))) except (BrokenPipeError, OSError): pass @property def freq_correction(self): return self.__freq_correction @freq_correction.setter def freq_correction(self, value): if value != self.__freq_correction: self.__freq_correction = value self.set_device_freq_correction(value) def set_device_freq_correction(self, value): try: self.parent_ctrl_conn.send( (self.Command.SET_FREQUENCY_CORRECTION.name, int(value))) except (BrokenPipeError, OSError): pass @property def direct_sampling_mode(self): return self.__direct_sampling_mode @direct_sampling_mode.setter def direct_sampling_mode(self, value): if value != self.__direct_sampling_mode: self.__direct_sampling_mode = value self.set_device_direct_sampling_mode(value) def set_device_direct_sampling_mode(self, value): try: self.parent_ctrl_conn.send( (self.Command.SET_DIRECT_SAMPLING_MODE.name, int(value))) except (BrokenPipeError, OSError): pass def start_rx_mode(self): self.init_recv_buffer() self.parent_data_conn, self.child_data_conn = Pipe(duplex=False) self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.is_receiving = True logger.info("{0}: Starting RX Mode".format(self.__class__.__name__)) self.receive_process = Process(target=self.receive_process_function, args=self.receive_process_arguments) self.receive_process.daemon = True self._start_read_rcv_buffer_thread() self._start_read_message_thread() try: self.receive_process.start() except OSError as e: logger.error(repr(e)) self.device_messages.append(repr(e)) def stop_rx_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 RX Mode: {1}".format( self.__class__.__name__, msg)) if hasattr(self, "receive_process") and self.receive_process.is_alive(): self.receive_process.join(self.JOIN_TIMEOUT) if self.receive_process.is_alive(): logger.warning( "{0}: Receive process is still alive, terminating it". format(self.__class__.__name__)) self.receive_process.terminate() self.receive_process.join() self.is_receiving = False for connection in (self.parent_ctrl_conn, self.parent_data_conn, self.child_ctrl_conn, self.child_data_conn): try: connection.close() except OSError as e: logger.exception(e) def start_tx_mode(self, samples_to_send: np.ndarray = None, repeats=None, resume=False): self.is_transmitting = True self.parent_ctrl_conn, self.child_ctrl_conn = Pipe() self.init_send_parameters(samples_to_send, repeats, resume=resume) logger.info("{0}: Starting TX Mode".format(self.__class__.__name__)) self.transmit_process = Process(target=self.send_process_function, args=self.send_process_arguments) self.transmit_process.daemon = True self._start_read_message_thread() self.transmit_process.start() 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) @staticmethod def bytes_to_iq(buffer) -> np.ndarray: pass @staticmethod def iq_to_bytes(complex_samples: np.ndarray): pass def read_device_messages(self): while self.is_receiving or self.is_transmitting: try: message = self.parent_ctrl_conn.recv() try: splitted = message.split(":") action = ":".join(splitted[:-1]) return_code = splitted[-1] self.log_retcode(int(return_code), action) except ValueError: self.device_messages.append("{0}: {1}".format( self.__class__.__name__, message)) except (EOFError, UnpicklingError, OSError, ConnectionResetError) as e: logger.info("Exiting read device message thread due to " + str(e)) break self.is_transmitting = False self.is_receiving = False logger.debug("Exiting read device errors thread") def read_receiving_queue(self): my_num_samples = SettingsProxy.get_receive_buffer_size(False, False) self.my_receive_buffer = IQArray(None, dtype=self.DATA_TYPE, n=int(my_num_samples)) self.my_current_recv_index = 0 while self.is_receiving: try: byte_buffer = self.parent_data_conn.recv_bytes() samples = self.bytes_to_iq(byte_buffer) n_samples = len(samples) if n_samples == 0: continue if self.apply_dc_correction: samples = samples - np.mean(samples, axis=0) except OSError as e: logger.exception(e) continue except EOFError: logger.info("EOF Error: Ending receive thread") break if self.current_recv_index + n_samples >= len(self.receive_buffer): if self.resume_on_full_receive_buffer: self.current_recv_index = 0 if n_samples >= len(self.receive_buffer): n_samples = len(self.receive_buffer) - 1 else: self.stop_rx_mode( "Receiving buffer is full {0}/{1}".format( self.current_recv_index + n_samples, len(self.receive_buffer))) return self.receive_buffer[self. current_recv_index:self.current_recv_index + n_samples] = samples[:n_samples] self.current_recv_index += n_samples if self.my_acess_record_iq: self.my_receive_buffer[self.my_current_recv_index:self. my_current_recv_index + n_samples] = samples[:n_samples] self.my_current_recv_index += n_samples logger.debug("Exiting read_receive_queue thread.") def init_send_parameters(self, samples_to_send: IQArray = None, repeats: int = None, resume=False): if samples_to_send is not None: if isinstance(samples_to_send, IQArray): samples_to_send = samples_to_send.convert_to(self.DATA_TYPE) else: samples_to_send = IQArray(samples_to_send).convert_to( self.DATA_TYPE) self.samples_to_send = samples_to_send self.send_buffer = None if self.send_buffer is None: if isinstance(self.samples_to_send, IQArray): self.send_buffer = self.iq_to_bytes(self.samples_to_send.data) else: self.send_buffer = self.iq_to_bytes(self.samples_to_send) elif not resume: self.current_sending_repeat = 0 if repeats is not None: self.sending_repeats = repeats
class SimpleQueue(BaseObject): # Construction/Destruction def __init__(self, reader=None, writer=None, init=True): self._rlock = Lock() if sys.platform == 'win32': self._wlock = None else: self._wlock = Lock() self._writer = None self._reader = None if init: self.construct(reader, writer) # Pickling def __getstate__(self): context.assert_spawning(self) return self._reader, self._writer, self._rlock, self._wlock def __setstate__(self, state): self._reader, self._writer, self._rlock, self._wlock = state self._poll = self._reader.poll # Constructors/Destructors def construct(self, reader=None, writer=None): if reader is None and writer is None: self.create_pipe() else: self._writer = writer self._reader = reader def create_pipe(self, duplex=False): self._reader, self._writer = Pipe(duplex) def empty(self): return not self._reader.poll() def get_reader(self): return self._reader def get_writer(self): return self._writer def get(self, block=True, timeout=None): if self._rlock.aqcuire(block, timeout): try: res = self._reader.recv_bytes() finally: self._rlock.release() else: warnings.warn() return None # unserialize the data after having released the lock return context.reduction.ForkingPickler.loads(res) async def get_async(self, timeout=None, interval=0.0): start_time = time.perf_counter() while True: if self._rlock.aqcuire(block=False): try: res = self._reader.recv_bytes() finally: self._rlock.release() break if timeout is not None and (time.perf_counter() - start_time) >= timeout: warnings.warn() return None await asyncio.sleep(interval) # unserialize the data after having released the lock return context.reduction.ForkingPickler.loads(res) def put(self, obj, block=True, timeout=None): # serialize the data before acquiring the lock obj = context.reduction.ForkingPickler.dumps(obj) if self._wlock is None: # writes to a message oriented win32 pipe are atomic self._writer.send_bytes(obj) else: if self._wlock.acquire(block, timeout): try: self._writer.send_bytes(obj) finally: self._wlock.release() else: warnings.warn() async def put_async(self, obj, timeout=None, interval=0.0): start_time = time.perf_counter() # serialize the data before acquiring the lock obj = context.reduction.ForkingPickler.dumps(obj) if self._wlock is None: # writes to a message oriented win32 pipe are atomic self._writer.send_bytes(obj) else: while True: if self._wlock.acquire(block=False): try: self._writer.send_bytes(obj) finally: self._wlock.release() break if timeout is not None and (time.perf_counter() - start_time) >= timeout: warnings.warn() return None await asyncio.sleep(interval) def close(self): self._reader.close() self._writer.close()