Пример #1
0
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())
Пример #2
0
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
Пример #3
0
 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()
Пример #4
0
 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()
Пример #5
0
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])
Пример #6
0
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)
Пример #7
0
    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')
Пример #8
0
    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)
Пример #9
0
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
Пример #10
0
 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
Пример #11
0
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()))
Пример #12
0
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
Пример #14
0
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'

Пример #15
0
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()
Пример #16
0
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()
Пример #17
0
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
Пример #18
0
    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))
Пример #19
0
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
Пример #20
0
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()
Пример #21
0
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
Пример #22
0
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
Пример #23
0
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)
Пример #24
0
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""
Пример #25
0
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
Пример #26
0
    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))
Пример #27
0
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)

Пример #28
0
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)
Пример #29
0
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
Пример #30
0
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()