def test_rate_tags_to_global(self): '''Test to ensure that rate tags go to the global segment and not to the capture segment''' src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file) # Set a value that will get overridden by the tags file_sink.set_global_meta("core:sample_rate", 20) injector = simple_tag_injector() tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() samp_rate = 1000.5 injector.inject_tag = {"rx_rate": samp_rate} sleep(.2) tb.stop() tb.wait() meta = json.load(open(json_file, "r")) # Samp rate should have been set by the tag assert meta["global"]["core:sample_rate"] == samp_rate # And should not be in the captures segment assert "core:sample_rate" not in meta["captures"][0]
def test_rx_time_conversion(self): '''Test that rx_time tags are correctly converted to iso8601 strings''' src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file) seconds = 1520551983 frac_seconds = 0.09375 frac_seconds_2 = 0.25 correct_str_1 = datetime.utcfromtimestamp( seconds).strftime('%Y-%m-%dT%H:%M:%S') correct_str_1 += str(frac_seconds).lstrip('0') + "Z" correct_str_2 = datetime.utcfromtimestamp( seconds).strftime('%Y-%m-%dT%H:%M:%S') correct_str_2 += str(frac_seconds_2).lstrip('0') + "Z" injector = simple_tag_injector() # first sample should have a rx_time tag injector.inject_tag = {"rx_time": (seconds, frac_seconds)} tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() sleep(.2) # Also test the case where a tag arives while writing injector.inject_tag = {"rx_time": (seconds, frac_seconds_2)} sleep(.1) tb.stop() tb.wait() with open(json_file, "r") as f: meta = json.load(f) assert meta["captures"][0]["core:datetime"] == correct_str_1 assert meta["captures"][1]["core:datetime"] == correct_str_2
def test_tags_to_capture_segment(self): src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file) injector = simple_tag_injector() tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() # Inject a bunch of tags that should make capture segments for i in range(100): sleep(.01) frac, int_part = math.modf(time.time()) injector.inject_tag = { "rx_freq": i * 1000, "rx_rate": i * 500, "rx_time": (int(int_part), frac) } tb.stop() tb.wait() metadata = json.load(open(json_file, "r")) # There should be 100 capture segments self.assertEqual(len(metadata["captures"]), 100) # And the data in them should match the tags we created for i in range(99): self.assertEqual( metadata["captures"][i + 1]["core:frequency"], i * 1000)
def test_tags_to_annotation_segments(self): '''Test that tags correctly convert to annotation segments''' # FIXME: this test is occasionally flaky, as the flowgraph is shutdown # before all the messages get to the sink src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file) injector = simple_tag_injector() tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() # Inject a bunch of tags that should make annotation segments for i in range(100): sleep(.001) frac, int_part = math.modf(time.time()) injector.inject_tag = {"test:a": i, "test:b": True, "test:c": 2.33} sleep(.5) tb.stop() tb.wait() metadata = json.load(open(json_file, "r")) # There should be 100 annotation segments self.assertEqual(len(metadata["annotations"]), 100) for i in range(100): self.assertEqual(metadata["annotations"][i]["test:a"], i) self.assertEqual(metadata["annotations"][i]["test:b"], True) self.assertEqual(metadata["annotations"][i]["test:c"], 2.33)
def test_relative_time_mode(self): # Example of Relative Mode Opertation # The following events happen: # Sample 0: rx_time: (2, 0.50000) at host time # of 2018-03-12T11:36:00.20000 # 10,000 samples follow # Sample 10,000: rx_time: (4, 0.80000) # 20,000 samples follow # Note that the relative time difference between the two # capture segments is precisely 2.3 seconds. # This should create two capture segments: # Capture Segment 1 core:datetime: 2018-03-12T11:36:00.20000 # Capture Segment 2 core:datetime: 2018-03-12T11:36:02.50000 limit_event = Event() continue_event = Event() samp_rate = 10000.0 limit_samples = samp_rate print(limit_samples) src = sample_producer(limit_samples, limit_event, continue_event) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file, sigmf.sigmf_time_mode_relative) file_sink.set_global_meta("core:sample_rate", samp_rate) injector = simple_tag_injector() # first sample should have a rx_time tag injector.inject_tag = {"rx_time": (2, 0.500000)} tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() print("waiting") limit_event.wait() # sleep to let the last samples get to the sink block sleep(.1) # set the rx_time tag for the next section injector.inject_tag = {"rx_time": (4, 0.80000)} continue_event.set() sleep(.1) tb.stop() tb.wait() with open(json_file, "r") as f: meta = json.load(f) capture_one_dt = parse_iso_ts(meta["captures"][0]["core:datetime"]) capture_two_dt = parse_iso_ts(meta["captures"][1]["core:datetime"]) diff_time = capture_two_dt - capture_one_dt assert diff_time.seconds == 2 assert diff_time.microseconds == 300000
def test_not_intially_open_capture_tag_offsets(self): '''Test that if a sink is created without a file initially open, and then a file is opened, that capture stream tags will have the correct offsets, i.e. they should be set from when the file was opened, not when the flowgraph started''' samp_rate = 200000 src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) description = "This is a test of the sigmf sink." author = "Just some person" file_license = "CC-0" hardware = "Sig Source" data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", "") file_sink.set_global_meta("core:sample_rate", samp_rate) file_sink.set_global_meta("core:description", description) file_sink.set_global_meta("core:author", author) file_sink.set_global_meta("core:sample_rate", author) file_sink.set_global_meta("core:license", file_license) file_sink.set_global_meta("core:hw", hardware) injector = simple_tag_injector() # build flowgraph here tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() time.sleep(.1) file_sink.open(data_file) time.sleep(.1) injector.inject_tag = {"rx_freq": 900e6} time.sleep(.1) tb.stop() tb.wait() injected_offset = injector.injected_offset with open(json_file, "r") as f: meta_str = f.read() meta = json.loads(meta_str) # Check global meta assert meta["global"]["core:description"] == description assert meta["global"]["core:author"] == author assert meta["global"]["core:license"] == file_license assert meta["global"]["core:hw"] == hardware # Check capture meta # The sample_start should be less than what it was injected # at, since no file was open at first, so the internal offsets # were off assert (meta["captures"][0] ["core:sample_start"] < injected_offset)
def test_stream_tags_before_file(self): '''Test that stream tags received before a file is opened will get correctly set as metadata''' samp_rate = 200000 src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) description = "This is a test of the sigmf sink." author = "Just some person" file_license = "CC-0" hardware = "Sig Source" data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", "") file_sink.set_global_meta("core:sample_rate", samp_rate) file_sink.set_global_meta("core:description", description) file_sink.set_global_meta("core:author", author) file_sink.set_global_meta("core:sample_rate", author) file_sink.set_global_meta("core:license", file_license) file_sink.set_global_meta("core:hw", hardware) injector = simple_tag_injector() # build flowgraph here tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() time.sleep(.1) injector.inject_tag = {"test:a": 1} time.sleep(.1) injector.inject_tag = {"rx_freq": 900e6} time.sleep(.2) file_sink.open(data_file) time.sleep(.5) tb.stop() tb.wait() with open(json_file, "r") as f: meta_str = f.read() meta = json.loads(meta_str) # Check global meta assert meta["global"]["core:description"] == description assert meta["global"]["core:author"] == author assert meta["global"]["core:license"] == file_license assert meta["global"]["core:hw"] == hardware print(meta) # Check captures meta assert meta["captures"][0]["core:frequency"] == 900e6 # Check annotations meta, should be empty, since annotations are # meant for specific samples and shouldn't be saved assert len(meta["annotations"]) == 0
def test_pmt_to_annotation(self): src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", data_file) injector = simple_tag_injector() sender = msg_sender() counter = sample_counter() tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, counter) tb.connect(counter, file_sink) tb.msg_connect(sender, "out", file_sink, "command") tb.start() # sleep so the streamed annotation isn't the first one sleep(.1) # Inject one tag injector.inject_tag = {"test:a": 1} # Wait again so that we know the tag got processed sleep(.1) # Then tell it to add 2 more via pmts, # one before the injected tag sender.send_msg({ "command": "set_annotation_meta", "sample_start": 1, "sample_count": 10, "key": "test:b", "val": 22 }) # and one after sender.send_msg({ "command": "set_annotation_meta", "sample_start": counter.count + 1, "sample_count": 10, "key": "test:c", "val": True }) sleep(.25) tb.stop() tb.wait() metadata = json.load(open(json_file, "r")) # should be 3 annotations self.assertEqual(len(metadata["annotations"]), 3) # And they should be these and in this order self.assertEqual(metadata["annotations"][0]["test:b"], 22) self.assertEqual(metadata["annotations"][1]["test:a"], 1) self.assertEqual(metadata["annotations"][2]["test:c"], True)
def test_relative_time_mode_initial_closed(self): '''Test relative time mode when the sink is initially not recording''' # limit_event = Event() # continue_event = Event() samp_rate = 100e6 limit_samples = samp_rate print(limit_samples) # src = sample_producer(limit_samples, limit_event, continue_event) src = analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, (1 + 1j)) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", "", sigmf.sigmf_time_mode_relative) file_sink.set_global_meta("core:sample_rate", samp_rate) injector = simple_tag_injector() # first sample should have a rx_time tag injector.inject_tag = {"rx_time": (65000, 0.500000)} tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() # sleep to let some samples get to the sink block sleep(.1) # set the rx_time tag for the next section file_sink.open(data_file) # Let some stuff get recorded sleep(.1) tb.stop() tb.wait() with open(json_file, "r") as f: meta = json.load(f) capture_one_dt = parse_iso_ts(meta["captures"][0]["core:datetime"]) now = datetime.utcnow() print(capture_one_dt) print(now) self.assertEqual(now.year, capture_one_dt.year, "Bad year in first capture segment") self.assertEqual(now.month, capture_one_dt.month, "Bad month in first capture segment") self.assertEqual(now.day, capture_one_dt.day, "Bad day in first capture segment")
def run_iteration(wait_full, wait_frac): limit_event = Event() continue_event = Event() samp_rate = 10000.0 limit_samples = (samp_rate * wait_full) + (samp_rate * wait_frac) print(limit_samples) src = sample_producer(limit_samples, limit_event, continue_event) data_file, json_file = self.temp_file_names() file_sink = sigmf.sink("cf32_le", "") file_sink.set_global_meta("core:sample_rate", samp_rate) seconds = 1520551983 frac_seconds = 0.09375 end_seconds = seconds + wait_full end_frac = frac_seconds + wait_frac if (end_frac > 1): end_seconds += 1 end_frac -= 1 correct_str = datetime.utcfromtimestamp( end_seconds).strftime('%Y-%m-%dT%H:%M:%S') correct_str += str(end_frac).lstrip('0') + "Z" injector = simple_tag_injector() # first sample should have a rx_time tag injector.inject_tag = {"rx_time": (seconds, frac_seconds)} tb = gr.top_block() tb.connect(src, injector) tb.connect(injector, file_sink) tb.start() print("waiting") limit_event.wait() # sleep to let the last samples get to the sink block sleep(.1) file_sink.open(data_file) continue_event.set() sleep(.1) tb.stop() tb.wait() with open(json_file, "r") as f: meta = json.load(f) print(meta) assert meta["captures"][0]["core:datetime"] == correct_str