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
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)
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")
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
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
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")