def run(self, suites_to_run, pause=False, write_output=True): for test_suite in self.test_suites: # Skip test suites that we don't want to run if suites_to_run != [] and (not test_suite in suites_to_run): continue print("[+] Testing suite: '%s'" % test_suite) summary = TestSummary(suite=test_suite, pause=pause) # Get all metadata files associated with the suite get_mtime = lambda f: os.stat(os.path.join(self.test_suites_directory, test_suite, f)).st_mtime metadata_files = [os.path.join(self.test_suites_directory, test_suite, x) for x in sorted(os.listdir(os.path.join(self.test_suites_directory, test_suite)), key=get_mtime) if x.endswith('.sigmf-meta')] # Parse metadata files for metadata_file in metadata_files: print("[+] %s" % metadata_file) data_file = os.path.splitext(metadata_file)[0] + '.sigmf-data' # Load sigmf data TODO abstract f = open(metadata_file, 'r') sigmf = SigMFFile(metadata=f.read()) if not sigmf.validate(): raise Exception("Invalid SigMF format") global_meta = sigmf.get_global_info() capture_meta = sigmf.get_capture_info(0) f.close() # Initialize test parameters sample_rate = global_meta["core:sample_rate"] # Get LoRa configuration capture_freq = capture_meta["core:frequency"] if "lora:frequency_offset" in capture_meta: frequency_offset = capture_meta["lora:frequency_offset"] else: frequency_offset = 0 transmit_freq = capture_meta["lora:frequency"] sf = capture_meta["lora:sf"] cr = capture_meta["lora:cr"] bw = int(capture_meta["lora:bw"]) prlen = capture_meta["lora:prlen"] crc = capture_meta["lora:crc"] implicit = capture_meta["lora:implicit"] lora_config = LoRaConfig(transmit_freq, sf, cr, bw, prlen, crc, implicit) # Get test case configuration payload = capture_meta["test:expected"] times = capture_meta["test:times"] test = Test(payload, times) # Build flowgraph tb = gr.top_block() file_source = blocks.file_source(gr.sizeof_gr_complex, data_file, False) lora_receiver = lora.lora_receiver(sample_rate, capture_freq, [868100000], bw, sf, False, 4, True, reduced_rate=False, decimation=1) throttle = blocks.throttle(gr.sizeof_gr_complex, sample_rate, True) message_socket_sink = lora.message_socket_sink("127.0.0.1", 40868, 2) freq_xlating_fir_filter = filter.freq_xlating_fir_filter_ccc(1, (firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING, 6.67)), frequency_offset, sample_rate) # Make connections tb.connect((file_source, 0), (throttle, 0)) tb.connect((throttle, 0), (freq_xlating_fir_filter, 0)) tb.connect((freq_xlating_fir_filter, 0), (lora_receiver, 0)) tb.msg_connect((lora_receiver, 'frames'), (message_socket_sink, 'in')) tb.start() tb.wait() decoded_data = self.server.get_payloads(times) # Output from the flowgraph summary.add(TestResult(decoded_data=decoded_data, lora_config=lora_config, test=test), print_intermediate=True) # Finally, export the result for the suite summary.export_summary(path=self.reports_directory, write_output=write_output)
def run(self, suites_to_run, pause=False, write_output=True): for test_suite in self.test_suites: # Skip test suites that we don't want to run if suites_to_run != [] and (not test_suite in suites_to_run): continue print("[+] Testing suite: '%s'" % test_suite) summary = TestSummary(suite=test_suite, pause=pause) # Get all metadata files associated with the suite get_mtime = lambda f: os.stat( os.path.join(self.test_suites_directory, test_suite, f) ).st_mtime metadata_files = [ os.path.join(self.test_suites_directory, test_suite, x) for x in sorted(os.listdir( os.path.join(self.test_suites_directory, test_suite)), key=get_mtime) if x.endswith('.sigmf-meta') ] # Parse metadata files for metadata_file in metadata_files: print("[+] %s" % metadata_file) data_file = os.path.splitext(metadata_file)[0] + '.sigmf-data' # Load sigmf data TODO abstract f = open(metadata_file, 'r') sigmf = SigMFFile(metadata=f.read()) if not sigmf.validate(): raise Exception("Invalid SigMF format") global_meta = sigmf.get_global_info() capture_meta = sigmf.get_capture_info(0) f.close() # Initialize test parameters sample_rate = global_meta["core:sample_rate"] # Get LoRa configuration capture_freq = capture_meta["core:frequency"] if "lora:frequency_offset" in capture_meta: frequency_offset = capture_meta["lora:frequency_offset"] else: frequency_offset = 0 transmit_freq = capture_meta["lora:frequency"] sf = capture_meta["lora:sf"] cr = capture_meta["lora:cr"] bw = int(capture_meta["lora:bw"]) prlen = capture_meta["lora:prlen"] crc = capture_meta["lora:crc"] implicit = capture_meta["lora:implicit"] lora_config = LoRaConfig(transmit_freq, sf, cr, bw, prlen, crc, implicit) # Get test case configuration payload = capture_meta["test:expected"] times = capture_meta["test:times"] test = Test(payload, times) # Build flowgraph tb = gr.top_block() file_source = blocks.file_source(gr.sizeof_gr_complex, data_file, False) lora_receiver = lora.lora_receiver(sample_rate, capture_freq, [868100000], bw, sf, False, 4, True, reduced_rate=False, decimation=1) throttle = blocks.throttle(gr.sizeof_gr_complex, sample_rate, True) message_socket_sink = lora.message_socket_sink( "127.0.0.1", 40868, 2) freq_xlating_fir_filter = filter.freq_xlating_fir_filter_ccc( 1, (firdes.low_pass(1, sample_rate, 200000, 100000, firdes.WIN_HAMMING, 6.67)), frequency_offset, sample_rate) # Make connections tb.connect((file_source, 0), (throttle, 0)) tb.connect((throttle, 0), (freq_xlating_fir_filter, 0)) tb.connect((freq_xlating_fir_filter, 0), (lora_receiver, 0)) tb.msg_connect((lora_receiver, 'frames'), (message_socket_sink, 'in')) tb.start() tb.wait() decoded_data = self.server.get_payloads( times) # Output from the flowgraph summary.add(TestResult(decoded_data=decoded_data, lora_config=lora_config, test=test), print_intermediate=True) # Finally, export the result for the suite summary.export_summary(path=self.reports_directory, write_output=write_output)
def run_gui(): window_input = WindowInput() capture_data_input = CaptureData() capture_text_blocks = dict() window_text_blocks = dict() f = SigMFFile() capture_selector_dict = dict() layout = [ [ Text('This is the APL SIGMF tool to archive RF datasets', size=(80, 1)) ], [ Text('Enter your data and signal captures below. You must include', auto_size_text=True), Text('required', text_color='red', font=DEFAULT_FONT + ('italic', ), auto_size_text=True), Text('fields.', size=(50, 1), auto_size_text=True) ], [Text('_' * 150, auto_size_text=True)] ] layout.append([Text('Global Data', font=('Arial', 12, 'bold'))]) num_components = 0 line = [] for el in window_input.iter_core(): size = (30, 1) if len(line) == 0 else (None, None) auto_size = True if len(line) == 0 else (10, 1) line.extend([ Text(el, justification='right', size=size, text_color='red' if el in window_input.req_tags else None, auto_size_text=auto_size) ]) if el in window_input.el_multiline: window_text_blocks.update({ el: Multiline(window_input.el_text.get(el, ''), key=el, tooltip=window_input.el_tooltips.get(el, None), size=(30, 2)) }) elif el in window_input.el_selector: window_text_blocks.update({ el: Combo(values=window_input.el_selector[el], key=el, size=window_input.el_size.get(el, (None, None))) }) elif el in window_input.el_checkbox: window_text_blocks.update({ el: Checkbox(window_input.el_text.get(el, ''), key=el, size=window_input.el_size.get(el, (None, None))) }) else: window_text_blocks.update({ el: InputText(window_input.el_text.get(el, ''), key=el, tooltip=window_input.el_tooltips.get(el, None)) }) line.append(window_text_blocks[el]) if el in window_input.el_units: line.append(Text(window_input.el_units[el])) num_components += 1 if num_components < window_input.first_line_size: continue layout.append(line) line = [] for el1, el2 in window_input.iter_x_secondary(2): line = [] for el, size in zip([el1, el2], [30, 22]): if el is None: continue color = 'red' if el in window_input.req_tags else None window_text_blocks.update({ el: InputText(window_input.el_text.get(el, ''), key=el, tooltip=window_input.el_tooltips.get(el, None)) }) line.extend([ Text(el, justification='right', size=(size, 1), text_color=color), window_text_blocks[el] ]) if el in window_input.el_units: line.append(Text(window_input.el_units[el], size=(5, 1))) else: line.append(Text('', size=(5, 1))) layout.append(line) layout.extend( [[Text('_' * 150, auto_size_text=True)], [Text('Individual Capture Data', font=('Arial', 12, 'bold'))], [ Text('Capture Selector', auto_size_text=True), combo_button, Text('', size=(10, 1)), Button('Add Capture', enable_events=True), Button('Remove Capture', enable_events=True, size=(15, 1)), Button('Clear Capture', enable_events=True, size=(15, 1)) ]]) for el1, el2, el3 in capture_data_input.iter_x(3): line = [] for el in [el1, el2, el3]: if el is None: continue capture_text_blocks.update({ el: InputText(key=el, tooltip=capture_data_input.el_tooltips.get(el, None)) }) color = 'red' if el in capture_data_input.req_tags else None line.extend([ Text(el, justification='right', size=(20, 1), text_color=color), capture_text_blocks[el] ]) if el in capture_data_input.el_units: line.append(Text(capture_data_input.el_units[el], size=(5, 1))) else: line.append(Text('', size=(5, 1))) layout.append(line) window_text_blocks.update( {WindowInput.DATA_FILE: InputText('', key=WindowInput.DATA_FILE)}) layout.extend([[Text('_' * 150, auto_size_text=True)], [Text('Data Location', font=('Arial', 12, 'bold'))], [ Text(WindowInput.DATA_FILE, size=(30, 1), justification='right', text_color='red'), window_text_blocks[WindowInput.DATA_FILE], FileBrowse() ], [ Text(WindowInput.OUTPUT_FOLDER, size=(30, 1), justification='right'), InputText('', key=WindowInput.OUTPUT_FOLDER), FolderBrowse(), submit_button ], [ Text(WindowInput.LOAD_PATH, size=(30, 1), justification='right'), InputText('', key=WindowInput.LOAD_PATH), FileBrowse(file_types=(("Archive Files", "*.sigmf"), )), load_button ], [validate_button, Button('View Data')]]) window = Window('APL SigMF Archive Creator', auto_size_buttons=False, default_element_size=(20, 1), auto_size_text=False, default_button_element_size=(10, 1)).Layout(layout) while True: validate_button.Update(text='Update') load_button.Update(text='Load') submit_button.Update(text='Save Archive') window.Refresh() event, values = window.Read() print(event, values) if event == 'Load Archive': load_path = values[WindowInput.LOAD_PATH] if load_path == '': show_error('No archive file provided') continue load_button.Update(text='Loading...') window.Refresh() print('reading from ', values[WindowInput.LOAD_PATH]) f = fromarchive(values[WindowInput.LOAD_PATH]) update_global_screen(window_input, window_text_blocks, f.get_global_info(), f) capture_selector_dict = {} for capture in f.get_captures(): add_capture(capture_data_input, capture, capture_selector_dict, f, from_archive=True) elif event == 'Data Type Help': PopupOK( 'Format: <TypeCharacters><ElementBitSize>_<Endianness>\n\n' '\tTypeCharacters:\n' '\t\tUnsigned data: \"u\"\n' '\t\tComplex data: \"c\"\n' '\t\tFixedpoint data: \"f\"\n' '\tElementBitSize:\n' '\t\t32 bits, 16 bits, or 8 bits\n' '\tEndianness:\n' '\t\tl: Little Endian\n' '\t\tb: Big Endian\n\n\n\n' 'Example: \"uc32_l\"\n' 'Unsigned complex data where each element is 32 bits, or 64 bits total, formatted in little endian.', title='Data Type Help') elif event == 'Update': validate_button.Update(text='Validating...') window.Refresh() window_data_type_dict = {} added = True for el in window_input.iter(): req_field = True if el in window_input.req_tags else False el_type = window_input.el_types.get(el, None) el_unit = window_input.el_units.get(el, None) if el in window_input.partial_component_list: added = added and add_sigmf_field(update_dictionary, values, el, window_data_type_dict, window_input.get_tag(el), required=req_field, type=el_type, unit=el_unit) else: added = added and add_sigmf_field( SigMFFile.set_global_field, values, el, f, window_input.get_tag(el), required=req_field, type=el_type, unit=el_unit) data_type_str = '' data_type_str += 'c' if bool( window_data_type_dict[WindowInput.DATA_TYPE_COMPLEX]) else '' data_type_str += 'f' if not bool(window_data_type_dict[ WindowInput.DATA_TYPE_FIXEDPOINT]) else '' data_type_str += 'u' if bool( window_data_type_dict[WindowInput.DATA_TYPE_UNSIGNED]) else '' data_type_str += str( window_data_type_dict[WindowInput.DATA_SAMPLE_SIZE]) + '_' data_type_str += 'l' if window_data_type_dict[ WindowInput.DATA_BYTE_ORDER] == 'little endian' else 'b' data_type_dict = {SigMFFile.DATATYPE_KEY: data_type_str} added = added and add_sigmf_field(SigMFFile.set_global_field, data_type_dict, SigMFFile.DATATYPE_KEY, f, SigMFFile.DATATYPE_KEY, required=True) print('HERE: ', window_data_type_dict) added = added and add_sigmf_field(SigMFFile.set_data_file, values, WindowInput.DATA_FILE, f, required=True) and added if not added: # requirement not given continue if validate_data(f): submit_button.Update(disabled=False, button_color=DEFAULT_BUTTON_COLOR) elif event == 'Capture Combo': capture_dict = capture_selector_dict[values['Capture Combo']] update_capture_screen(capture_data_input, capture_text_blocks, capture_dict) elif event == 'Add Capture': add_capture(capture_data_input, values, capture_selector_dict, f) elif event == 'Remove Capture': capture_dict = dict() added = add_sigmf_field(update_dictionary, values, CaptureData.START_INDEX, capture_dict, SigMFFile.START_INDEX_KEY, required=True, type=int) if not added: # requirement not given continue captures = [] for capture in f._metadata[SigMFFile.CAPTURE_KEY]: if capture[SigMFFile.START_INDEX_KEY] != capture_dict[ SigMFFile.START_INDEX_KEY]: captures.append(capture) f._metadata[SigMFFile.CAPTURE_KEY] = captures annotations = [] for annotation in f._metadata[SigMFFile.ANNOTATION_KEY]: if annotation[SigMFFile.START_INDEX_KEY] != capture_dict[ SigMFFile.START_INDEX_KEY]: annotations.append(annotation) f._metadata[SigMFFile.ANNOTATION_KEY] = annotations new_values = list(combo_button.Values) rm_val = 'Capture {}'.format( capture_dict[SigMFFile.START_INDEX_KEY]) if rm_val in capture_selector_dict: capture_selector_dict.pop(rm_val) if rm_val in new_values: new_values.remove(rm_val) combo_button.Update(values=new_values, set_to_index=0) capture_dict = capture_selector_dict.get( combo_button.DefaultValue, None) update_capture_screen(capture_data_input, capture_text_blocks, capture_dict) elif event == 'Clear Capture': update_capture_screen(capture_data_input, capture_text_blocks, None) elif event == 'View Data': PopupOK('Current data:\n', f.dumps(pretty=True), title='') elif event == 'Save Archive': output_folder = values[WindowInput.OUTPUT_FOLDER] if output_folder == '': show_error('No output folder provided') continue elif len(capture_selector_dict.keys()) == 0: show_error('No capture data specified') submit_button.Update(text='Saving...') window.Refresh() archive_file = output_folder + '/' + os.path.basename( f.data_file).split('.')[0] + SIGMF_ARCHIVE_EXT f.archive(archive_file) PopupOK('Saved archive as \n', archive_file, title='') elif event in ['Cancel', None, 'Exit']: window.Close() break window.Close()