Ejemplo n.º 1
0
    def handle_msg(self, msg_pmt):
        msg = pmt.cdr(msg_pmt)
        if not pmt.is_u8vector(msg):
            print("[ERROR] Received invalid message type. Expected u8vector")
            return

        syms = np.array(pmt.u8vector_elements(msg), dtype='uint8')

        decodable_blocks = int(len(syms)/self.SYMS_PER_BLOCK)
        if decodable_blocks < self.total_num_blocks:
            # can't decode a partial block or a set of too few blocks
            print("[WARNING] Insufficient number of blocks provided; %d given but need %d for %d bytes" %
                  (decodable_blocks, self.total_num_blocks, self.msg_size))
            return

        num_blocks = min(decodable_blocks, self.total_num_blocks)
        byts = np.zeros(self.BYTES_PER_BLOCK*num_blocks, dtype=np.uint8)

        for block in range(num_blocks):
            byts_i = block*self.BYTES_PER_BLOCK
            syms_i = block*self.SYMS_PER_BLOCK
            byts[byts_i:byts_i+self.BYTES_PER_BLOCK] = self.decode_block(syms[syms_i:syms_i+self.SYMS_PER_BLOCK])

        # ignore first few bytes of first block as these contain packet metadata
        # cut off the rest to the requested length
        byts_arr = array.array('B', byts[self.HEADER_BLOCK_BYTES:self.HEADER_BLOCK_BYTES + self.msg_size])
        if self.print_packets:
            print(self._bytearr_to_string(byts_arr))

        self.message_port_pub(pmt.intern('out'), pmt.cons(pmt.get_PMT_NIL(), pmt.init_u8vector(len(byts_arr), byts_arr)))
        self.num_packets += 1
Ejemplo n.º 2
0
    def handle_msg(self, msg_pmt):
        meta = pmt.car(msg_pmt)
        msg = pmt.cdr(msg_pmt)
        if not pmt.is_u8vector(msg):
            print "[ERROR] Received invalid message type. Expected u8vector"
            return

        raw_vec = pmt.dict_ref(meta, pmt.intern("raw"), pmt.get_PMT_NIL())
        if raw_vec != pmt.get_PMT_NIL() and pmt.is_u8vector(raw_vec):
            raw = equisat_telemetry_parser.bytes_to_hex_str(
                pmt.u8vector_elements(raw_vec))
        else:
            print "[WARNING] No raw field provided in PDU; not publishing raw transmission"
            raw = None

        corrected = equisat_telemetry_parser.bytes_to_hex_str(
            pmt.u8vector_elements(msg))
        self.submit_packet(raw, corrected)
        time.sleep(self.MIN_REQUEST_PERIOD)
Ejemplo n.º 3
0
    def send_taps(self, fft_size):

        self.fft_size = fft_size
        self.taps_set = True
        taps = self.tap_equation(fft_size)
        taps_fi = self.gen_fixed_filter(taps, fft_size)
        taps_vec = self.gen_tap_vec(taps_fi, fft_size)
        data_rfnoc = pmt.init_s32vector(len(taps_vec), taps_vec.tolist())
        msg = pmt.cons(pmt.get_PMT_NIL(), data_rfnoc)
        # print(msg)
        self.message_port_pub(pmt.intern('to_rfnoc'), msg)
        print("done sending")
Ejemplo n.º 4
0
    def send(self): #  , input_items, output_items):
        #output_items[0][:] = input_items[0]
        # consume(0, len(input_items[0]))
        # print "sent flag = %d" % self.sent_flag
        if self.sent_flag == 0:
            start_time = 315964800
            epoch_length = 7200
            code_length = 12288
            key = [0x54, 0x65, 0x17, 0x98, 0x13, 0x65, 0x34, 0x87, 0x087, 0x14,
                   0x57, 0x81, 0x30, 0x13, 0x20, 0x23, 0x13, 0x13,
                   0x05, 0x43, 0x40, 0x54, 0x34, 0x67, 0x89, 0x14,
                   0x54, 0x18, 0x94, 0x10, 0x35, 0x00]

            key = "".join([chr(item) for item in key])

            current_time = 1452709080
            # current_time = 0
            # current_time = 1461629066 #time.time()

            adjusted_time = current_time - start_time
            adjusted_time = adjusted_time - (adjusted_time % epoch_length)

            print "adjusted time = {}".format(adjusted_time)
            pt = numpy.zeros(code_length/8, dtype=numpy.uint8)
            pt = "".join([chr(item) for item in pt])

            ctr = Counter.new(128, initial_value=adjusted_time)
            cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
            ct = cipher.encrypt(pt)
            cipher_stream = numpy.uint8([ord(item) for item in ct])

            spreading = numpy.zeros(code_length/8, dtype=numpy.uint8)
            for index in range(0, len(cipher_stream)):
        	temp = numpy.binary_repr(cipher_stream[index], width=8)
        	spreading[index] = int(temp[::-1], 2)

            spreading = numpy.fliplr(spreading.reshape(code_length/8/16, 16))
            spreading = spreading.reshape(code_length/8)
            spreading = numpy.fliplr(spreading.reshape(code_length/8/4, 4))
            data = spreading.reshape(code_length/8).view("uint32")

            #pmt_seq = pmt.make_u32vector(len(data), 0)

            #for i, val in enumerate(data):
            #    pmt.u32vector_set(pmt_seq, i, 0xffffffff) #True) # val)

            #self.message_port_pub(pmt.intern("scramb_seq"), pmt_seq)
            #print data
            print "1 %s" % type(data[0])
            data_len = len(data)
            data_pmt = pmt.to_pmt(data)
            #print data_pmt
            data = pmt.u32vector_elements(pmt.to_pmt(data))
            #print data
            # print type(data)
            data = pmt.init_u32vector(data_len, data)
            #print data_len
            #print data

            meta = pmt.get_PMT_NIL()
            # msg = pmt.cons(meta, data)
            # print data
            self.message_port_pub(self.msg_buf_out, pmt.cons(meta, data))

            # print "sent message"
            time.sleep(5)
            self.sent_flag = 1
Ejemplo n.º 5
0
    def general_work(self, input_items, output_items):
        """ Called by GNU Radio with input stream """
        # NOTE: input_items always includes self.NUM_OLD_DATA "old" bytes
        # we've already read, plus possibly more if we didn't consume them,
        # but the rest are new (see set_history above)
        inpt = input_items[0]
        new_inpt = inpt[self.HISTORY_LEN:]

        # finite state machine for different sections of packet
        if self.state is self.ST_WAIT_FOR_PREAMBLE:
            # if searching, check for start of preamble in the HISTORY and
            # set up for start of packet if found
            found, start, end, high, low = self.check_for_preamble(inpt, self.min_preamble_len, self.max_symbol_ratio)

            # if we found a preamble sequence, but it took the whole buffer
            # (i.e. the last preamble sequence was within one sequence of the end)
            # defer and try again next time in case there's more
            # otherwise, continue
            if found and end < len(inpt)-4:
                # setup packet state
                self.high = high
                self.low = low
                # consume the component of the preamble that we haven't already (the part not in the history)
                # note that end should always be greater than or equal to the history otherwise we would've done
                # this already, but check that it's greater than zero anyways
                new_preamble_len = max(0, end - self.HISTORY_LEN)
                self.consume(0, new_preamble_len)
                # now, try and start reading the frame sync
                self.state = self.ST_IN_FRAME_SYNC
            else:
                # if no preamble was found, consume all the data (if there was a partial preamble,
                # it will end up in the history)
                self.consume(0, len(new_inpt)) # TODO: setting this to len(inpt) instead makes this block actually terminate

            return 0

        elif self.state == self.ST_IN_FRAME_SYNC:
            # check if the new data is enough to complete the frame sync
            if len(new_inpt) >= self.FRAME_SYNC_LEN:
                # move onto blocks, starting past end of frame sync
                self.state = self.ST_IN_BLOCKS
                # consume the frame sync
                self.consume(0, self.FRAME_SYNC_LEN)

            return 0

        elif self.state == self.ST_IN_BLOCKS:
            # copy the input into a buffer to transmit later, not consuming data that overflows that buffer
            blocks_buf_rem = len(self.blocks_buf) - self.blocks_buf_i
            transferred = min(blocks_buf_rem, len(new_inpt))
            self.blocks_buf[self.blocks_buf_i:self.blocks_buf_i+transferred] = new_inpt[:transferred]
            self.blocks_buf_i += transferred
            self.consume(0, transferred)

            if self.blocks_buf_i >= len(self.blocks_buf): # should only equal
                # now that we have a full buffer, convert to symbols
                syms = self.get_symbols(self.blocks_buf, high=self.high, low=self.low, sym_seperation_thresh=self.SYM_SEPERATION_THRESH)

                # send message with symbols and reset state
                syms_arr = array.array('B', syms)
                self.message_port_pub(pmt.intern('out'),
                                      pmt.cons(pmt.get_PMT_NIL(), pmt.init_u8vector(len(syms_arr), syms_arr)))
                self.reset_state()

            return 0

        else:  # revert
            assert False
    def general_work(self, input_items, output_items):
        """ Called by GNU Radio with input stream """
        # NOTE: input_items always includes self.NUM_OLD_DATA "old" bytes
        # we've already read, plus possibly more if we didn't consume them,
        # but the rest are new (see set_history above)
        inpt = input_items[0]
        new_inpt = inpt[self.HISTORY_LEN:]

        # finite state machine for different sections of packet
        if self.state is self.ST_WAIT_FOR_PREAMBLE:
            # if searching, check for start of preamble in the HISTORY and
            # set up for start of packet if found
            found, start, end, high, low = self.check_for_preamble(
                inpt, self.min_preamble_len, self.max_symbol_ratio)

            if found and end >= len(inpt) - 4:
                # if we found a preamble sequence, but it took the whole buffer
                # (i.e. the last preamble sequence was within one sequence of the end)
                # defer and try again next time in case there's more
                # (we're guaranteed to find it again and will likely have more data after it)
                return 0
            elif found:
                # otherwise, continue:
                # setup packet state
                self.high = high
                self.low = low
                # consume the component of the preamble that we haven't already (the part not in the history)
                # note that end should almost always be greater than or equal to the history (otherwise we would've done
                # this already), unless we're just coming from a frame sync search which happened to consume part of a preamble
                new_preamble_len = max(0, end - self.HISTORY_LEN)
                self.consume_each(new_preamble_len)
                # now, try and start reading the frame sync
                self.state = self.ST_FRAME_SYNC_SEARCH
            else:
                # if no preamble was found, consume all the data (if there was a partial preamble,
                # it will end up in the history)
                self.consume_each(
                    len(new_inpt)
                )  # TODO: setting this to len(inpt) instead makes this block actually terminate

            return 0

        elif self.state == self.ST_FRAME_SYNC_SEARCH:
            # convert to symbols for speed
            new_inpt_syms = self.get_symbols(new_inpt, self.high, self.low)
            # search from the last search start to the end of the new input
            for i in range(self.frame_sync_searched,
                           len(new_inpt) - self.FRAME_SYNC_LEN):
                cur_buf = new_inpt_syms[i:i + self.FRAME_SYNC_LEN]

                # look for the most accurate section of frame sync before we have to stop searching
                # (wait until we're done searching otherwise we'll just take the first choice over the threshold)
                percent_correct = np.sum(
                    cur_buf == self.FRAME_SYNC_SYMS) / float(
                        self.FRAME_SYNC_LEN)
                if percent_correct >= self.best_frame_sync_match:  # emphasize later ones
                    self.best_frame_sync_match = percent_correct
                    self.best_frame_sync_index = self.frame_sync_searched

                elif self.frame_sync_searched > self.max_frame_sync_searched:
                    # check percent match threshold once we've exhausted the  search space
                    if self.best_frame_sync_match > self.MIN_FRAME_SYNC_MATCH:
                        self.state = self.ST_IN_BLOCKS
                        self.consume_each(self.best_frame_sync_index +
                                          self.FRAME_SYNC_LEN - 1)
                    else:
                        self.reset_state()
                        self.consume_each(self.frame_sync_searched - 1)
                    return 0

                self.frame_sync_searched += 1

            return 0

        elif self.state == self.ST_IN_BLOCKS:
            # copy the input into a buffer to transmit later, not consuming data that overflows that buffer
            blocks_buf_rem = len(self.blocks_buf) - self.blocks_buf_i
            transferred = min(blocks_buf_rem, len(new_inpt))
            self.blocks_buf[self.blocks_buf_i:self.blocks_buf_i +
                            transferred] = new_inpt[:transferred]
            self.blocks_buf_i += transferred
            self.consume_each(transferred)

            if self.blocks_buf_i >= len(self.blocks_buf):  # should only equal
                # now that we have a full buffer, convert to symbols
                syms = self.get_symbols(
                    self.blocks_buf,
                    high=self.high,
                    low=self.low,
                    sym_seperation_thresh=self.SYM_SEPERATION_THRESH)

                # send message with symbols and reset state
                syms_arr = array.array('B', syms)
                self.message_port_pub(
                    pmt.intern('out'),
                    pmt.cons(pmt.get_PMT_NIL(),
                             pmt.init_u8vector(len(syms_arr), syms_arr)))
                self.reset_state()

            return 0

        else:  # revert
            assert False
Ejemplo n.º 7
0
    def decode_worker(dec_queue, stopping):
        try:
            while not stopping.value:
                try:
                    # block until next demod is in
                    next_demod = dec_queue.get(timeout=QUEUE_EMPTY_POLL_PERIOD)
                except Queue.Empty:
                    # check for stopped condition if queue empty after timeout
                    continue
                except KeyboardInterrupt:
                    return

                try:
                    wavfilename = next_demod["wavfilename"]
                    sample_rate, duration, nframes = DecoderQueue.get_audio_info(wavfilename)

                    # spawn the GNU radio flowgraph and run it
                    tb = equisat_fm_demod(wavfile=wavfilename, sample_rate=sample_rate)
                    logger.debug("[%s] Starting demod flowgraph" % wavfilename)
                    tb.start()
                    # run until the wav source block has completed
                    # (GNU Radio has a bug such that flowgraphs with Python message passing blocks won't terminate)
                    # (see https://github.com/gnuradio/gnuradio/pull/797, https://www.ruby-forum.com/t/run-to-completion-not-working-with-message-passing-blocks/240759)
                    start = time.time()
                    while tb.blocks_wavfile_source_0.nitems_written(0) < nframes \
                        and (time.time() - start) < MAX_FLOWGRAPH_RUNTIME:
                        time.sleep(FLOWGRAPH_POLL_PERIOD_S)
                    
                    if tb.blocks_wavfile_source_0.nitems_written(0) < nframes:
                        logger.warn("[%s] Flowgraph timed out (%d/%d frames)" % \
                            (wavfilename, tb.blocks_wavfile_source_0.nitems_written(0), nframes))
                            
                    logger.debug("[%s] Stopping demod flowgraph" % wavfilename)
                    tb.stop()
                    tb.wait()
                    logger.debug("[%s] Demod flowgraph terminated" % wavfilename)

                    # we have a block to store both all valid raw packets and one to store
                    # all those that passed error correction (which includes the corresponding raw)
                    raw_packets = []
                    corrected_packets = []

                    for i in range(tb.message_store_block_raw.num_messages()):
                        msg = tb.message_store_block_raw.get_message(i)
                        raw_packets.append(binascii.hexlify(bytearray(pmt.u8vector_elements(pmt.cdr(msg)))))

                    for i in range(tb.message_store_block_corrected.num_messages()):
                        msg = tb.message_store_block_corrected.get_message(i)
                        corrected = pmt.u8vector_elements(pmt.cdr(msg))
                        raw = pmt.u8vector_elements(pmt.dict_ref(pmt.car(msg), pmt.intern("raw"), pmt.get_PMT_NIL()))
                        decoded, decode_errs = packetparse.parse_packet(binascii.hexlify(bytearray(corrected)))
                        corrected_packets.append({
                            "raw": binascii.hexlify(bytearray(raw)),
                            "corrected": binascii.hexlify(bytearray(corrected)),
                            "parsed": decoded,
                            "decode_errs": decode_errs
                        })

                    onfinish = next_demod["onfinish"]
                    onfinish(wavfilename, {
                        "raw_packets": raw_packets,
                        "corrected_packets": corrected_packets,
                    }, next_demod["args"], None)

                except KeyboardInterrupt:
                    return
                except Exception as ex:
                    logger.error("Exception in decoder worker, skipping job")
                    logger.exception(ex)
                    onfinish = next_demod["onfinish"]
                    onfinish(next_demod["wavfilename"], {
                        "raw_packets": [],
                        "corrected_packets": [],
                    }, next_demod["args"], ex.message)

        finally:
            print("Stopping decoder worker")