Exemplo n.º 1
0
    def __call__(self, schedule_entry_name, task_id):
        """This is the entrypoint function called by the scheduler."""
        from tasks.models import TaskResult

        # Raises TaskResult.DoesNotExist if no matching task result
        task_result = TaskResult.objects.get(
            schedule_entry__name=schedule_entry_name, task_id=task_id
        )

        self.test_required_components()

        for recording_id, measurement_params in enumerate(
            self.measurement_params_list, start=1
        ):
            start_time = utils.get_datetime_str_now()
            data = self.acquire_data(measurement_params, task_id)
            end_time = utils.get_datetime_str_now()
            sigmf_md = self.build_sigmf_md(
                task_id,
                measurement_params,
                data,
                task_result.schedule_entry,
                recording_id,
                start_time,
                end_time,
            )
            self.archive(task_result, recording_id, data, sigmf_md)
Exemplo n.º 2
0
    def acquire_data(self, fc, parent_entry, task_id):
        tuning_parameters = self.tuning_parameters[fc]
        self.configure_usrp(fc, **tuning_parameters)

        # Use the radio's actual reported sample rate instead of requested rate
        sample_rate = self.usrp.radio.sample_rate

        # Build global metadata
        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sigmf_md.set_global_field("core:sample_rate", sample_rate)
        sigmf_md.set_global_field("core:description", self.description)

        sensor_def = capabilities['sensor_definition']
        sigmf_md.set_global_field("ntia:sensor_definition", sensor_def)
        sigmf_md.set_global_field("ntia:sensor_id", settings.FQDN)
        sigmf_md.set_global_field("scos:version", SCOS_TRANSFER_SPEC_VER)

        # Acquire data and build per-capture metadata
        data = np.array([], dtype=np.complex64)

        nsamps = int(sample_rate * tuning_parameters['duration_ms'] * 1e-3)

        dt = utils.get_datetime_str_now()
        acq = self.usrp.radio.acquire_samples(nsamps).astype(np.complex64)
        data = np.append(data, acq)
        capture_md = {"core:frequency": fc, "core:datetime": dt}
        sigmf_md.add_capture(start_index=0, metadata=capture_md)
        annotation_md = {"applied_scale_factor": self.usrp.radio.scale_factor}
        sigmf_md.add_annotation(start_index=0, length=nsamps,
                                metadata=annotation_md)

        return data, sigmf_md
Exemplo n.º 3
0
def status(request, version, format=None):
    """The status overview of the sensor."""
    return Response({
        "scheduler": scheduler.thread.status,
        "location": serialize_location(),
        "system_time": utils.get_datetime_str_now(),
        "last_calibration_time": get_last_calibration_time(),
    })
    def __call__(self, schedule_entry_name, task_id):
        """This is the entrypoint function called by the scheduler."""
        from tasks.models import TaskResult

        # Raises TaskResult.DoesNotExist if no matching task result
        task_result = TaskResult.objects.get(
            schedule_entry__name=schedule_entry_name, task_id=task_id)

        self.test_required_components()
        self.configure_sdr()
        start_time = utils.get_datetime_str_now()
        data = self.acquire_data()
        end_time = utils.get_datetime_str_now()
        m4s_data = self.apply_detector(data)
        sigmf_md = self.build_sigmf_md(task_id, data,
                                       task_result.schedule_entry, start_time,
                                       end_time)
        self.archive(task_result, m4s_data, sigmf_md)
Exemplo n.º 5
0
def status(request, version, format=None):
    """The status overview of the sensor."""
    context = {'request': request}
    taskq = scheduler.thread.task_queue.to_list()[:settings.MAX_TASK_QUEUE]
    task_serializer = TaskSerializer(taskq, many=True, context=context)

    return Response({
        'scheduler': scheduler.thread.status,
        'location': get_location(),
        'system_time': utils.get_datetime_str_now(),
        'task_queue': task_serializer.data
    })
    def build_sigmf_md(self):
        logger.debug("Building SigMF metadata file")

        sigmf_md = SigMFFile()
        sigmf_md.set_global_field("core:datatype", "rf32_le")
        sigmf_md.set_global_field("core:sample_rate", self.sample_rate)
        sigmf_md.set_global_field("core:description", self.description)

        # get() expects a single object - currently there are none and this fails.
        # how do I put one in?
        #sensor_def_obj = SensorDefinition.objects.get()
        #sensor_def_json = SensorDefinitionSerializer(sensor_def_obj).data
        #sigmf_md.set_global_field("scos:sensor_definition", sensor_def_json)

        try:
            fqdn = settings.ALLOWED_HOSTS[1]
        except IndexError:
            fqdn = 'not.set'

        sigmf_md.set_global_field("scos:sensor_id", fqdn)
        sigmf_md.set_global_field("scos:version", SCOS_TRANSFER_SPEC_VER)

        capture_md = {
            "core:frequency": self.frequency,
            "core:time": utils.get_datetime_str_now()
        }

        sigmf_md.add_capture(start_index=0, metadata=capture_md)

        # for i, detector in enumerate(M4sDetector):
        #     single_frequency_fft_md = {
        #         "number_of_samples_in_fft": self.fft_size,
        #         "window": "blackman",
        #         "equivalent_noise_bandwidth": self.enbw,
        #         "detector": detector.name + "_power",
        #         "number_of_ffts": self.nffts,
        #         "units": "dBm",
        #         "reference": "not referenced"
        #     }

        #     annotation_md = {
        #         "scos:measurement_type": {
        #             "single_frequency_fft_detection": single_frequency_fft_md,
        #         }
        #     }

        #     sigmf_md.add_annotation(
        #         start_index=(i * self.fft_size),
        #         length=self.fft_size,
        #         metadata=annotation_md
        #     )

        return sigmf_md
Exemplo n.º 7
0
    def build_sigmf_md(self):
        logger.debug("Building SigMF metadata file")

        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sigmf_md.set_global_field("core:sample_rate", self.sample_rate)
        sigmf_md.set_global_field("core:description", self.description)

        try:
            sensor_def_obj = SensorDefinition.objects.get()
            sensor_def = SensorDefinitionSerializer(sensor_def_obj).data
            sigmf_md.set_global_field("scos:sensor_definition", sensor_def)
        except SensorDefinition.DoesNotExist:
            pass

        try:
            fqdn = settings.ALLOWED_HOSTS[1]
        except IndexError:
            fqdn = 'not.set'

        sigmf_md.set_global_field("scos:sensor_id", fqdn)
        sigmf_md.set_global_field("scos:version", SCOS_TRANSFER_SPEC_VER)

        capture_md = {
            "core:frequency": self.frequency,
            "core:time": utils.get_datetime_str_now()
        }

        sigmf_md.add_capture(start_index=0, metadata=capture_md)

        for i, detector in enumerate(M4sDetector):
            single_frequency_fft_md = {
                "number_of_samples_in_fft": self.fft_size,
                "window": "blackman",
                "equivalent_noise_bandwidth": self.enbw,
                "detector": detector.name + "_power",
                "number_of_ffts": self.nffts,
                "units": "dBm",
                "reference": "not referenced"
            }

            annotation_md = {
                "scos:measurement_type": {
                    "single_frequency_fft_detection": single_frequency_fft_md,
                }
            }

            sigmf_md.add_annotation(start_index=(i * self.fft_size),
                                    length=self.fft_size,
                                    metadata=annotation_md)

        return sigmf_md
Exemplo n.º 8
0
    def build_sigmf_md(self):
        logger.debug("Building SigMF metadata file")

        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sigmf_md.set_global_field("core:sample_rate", self.sample_rate)
        sigmf_md.set_global_field("core:description", self.description)

        sensor_def = capabilities['sensor_definition']
        sigmf_md.set_global_field("ntia:sensor_definition", sensor_def)
        sigmf_md.set_global_field("ntia:sensor_id", settings.FQDN)
        sigmf_md.set_global_field("scos:version", SCOS_TRANSFER_SPEC_VER)

        capture_md = {
            "core:frequency": self.frequency,
            "core:time": utils.get_datetime_str_now()
        }

        sigmf_md.add_capture(start_index=0, metadata=capture_md)

        for i, detector in enumerate(M4sDetector):
            single_frequency_fft_md = {
                "number_of_samples_in_fft": self.fft_size,
                "window": "blackman",
                "equivalent_noise_bandwidth": self.enbw,
                "detector": detector.name + "_power",
                "number_of_ffts": self.nffts,
                "units": "dBm",
                "reference": "not referenced"
            }

            annotation_md = {
                "scos:measurement_type": {
                    "single_frequency_fft_detection": single_frequency_fft_md,
                }
            }

            sigmf_md.add_annotation(start_index=(i * self.fft_size),
                                    length=self.fft_size,
                                    metadata=annotation_md)

        return sigmf_md
    def acquire_data(self, parent_entry, task_id):
        # Build global metadata
        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sigmf_md.set_global_field("core:sample_rate", self.sample_rate)
        sigmf_md.set_global_field("core:description", self.description)

        try:
            sensor_def_obj = SensorDefinition.objects.get()
            sensor_def = SensorDefinitionSerializer(sensor_def_obj).data
            sigmf_md.set_global_field("scos:sensor_definition", sensor_def)
        except SensorDefinition.DoesNotExist:
            pass

        try:
            fqdn = settings.ALLOWED_HOSTS[1]
        except IndexError:
            fqdn = 'not.set'

        sigmf_md.set_global_field("scos:sensor_id", fqdn)
        sigmf_md.set_global_field("scos:version", SCOS_TRANSFER_SPEC_VER)

        # Acquire data and build per-capture metadata
        data = np.array([], dtype=np.complex64)
        nsamps = self.nsamples

        for idx, fc in enumerate(self.fcs):
            self.usrp.radio.tune_frequency(fc)
            dt = utils.get_datetime_str_now()
            acq = self.usrp.radio.acquire_samples(nsamps).astype(np.complex64)
            data = np.append(data, acq)
            start_idx = idx * nsamps
            capture_md = {"core:frequency": fc, "core:datetime": dt}
            sigmf_md.add_capture(start_index=start_idx, metadata=capture_md)
            annotation_md = {
                "applied_scale_factor": self.usrp.radio.scale_factor
            }
            sigmf_md.add_annotation(start_index=start_idx, length=nsamps,
                                    metadata=annotation_md)

        return data, sigmf_md
Exemplo n.º 10
0
    def build_sigmf_md(self, task_id, measurement_params, data):
        # Build global metadata
        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sample_rate = self.sdr.radio.sample_rate
        sigmf_md.set_global_field("core:sample_rate", sample_rate)

        sensor_def = capabilities["sensor_definition"]
        sensor_def["id"] = settings.FQDN
        sigmf_md.set_global_field("ntia-sensor:sensor", sensor_def)

        action_def = {
            "name": self.name,
            "description": self.description,
            "type": ["TimeDomain"],
        }

        sigmf_md.set_global_field("ntia-scos:action", action_def)
        sigmf_md.set_global_field("ntia-scos:task_id", task_id)

        dt = utils.get_datetime_str_now()

        num_samples = measurement_params.get_num_samples()

        capture_md = {
            "core:frequency": self.sdr.radio.frequency,
            "core:datetime": dt
        }
        sigmf_md.add_capture(start_index=0, metadata=capture_md)
        calibration_annotation_md = self.sdr.radio.create_calibration_annotation(
        )
        sigmf_md.add_annotation(start_index=0,
                                length=num_samples,
                                metadata=calibration_annotation_md)

        time_domain_detection_md = {
            "ntia-core:annotation_type": "TimeDomainDetection",
            "ntia-algorithm:detector": "sample_iq",
            "ntia-algorithm:detection_domain": "time",
            "ntia-algorithm:number_of_samples": num_samples,
            "ntia-algorithm:units": "volts",
            "ntia-algorithm:reference": "not referenced",
        }
        sigmf_md.add_annotation(start_index=0,
                                length=num_samples,
                                metadata=time_domain_detection_md)

        # Recover the sigan overload flag
        sigan_overload = self.sdr.radio.sigan_overload

        # Check time domain average power versus calibrated compression
        time_domain_avg_power = 10 * np.log10(np.mean(np.abs(data)**2))
        time_domain_avg_power += (10 * np.log10(1 / (2 * 50)) + 30
                                  )  # Convert log(V^2) to dBm
        sensor_overload = (
            time_domain_avg_power >
            self.sdr.radio.sensor_calibration_data["1db_compression_sensor"])

        # Create SensorAnnotation and add gain setting and overload indicators
        sensor_annotation_md = {
            "ntia-core:annotation_type": "SensorAnnotation",
            "ntia-sensor:overload_sensor": sensor_overload,
            "ntia-sensor:overload_sigan": sigan_overload,
            "ntia-sensor:gain_setting_sigan": measurement_params.gain,
        }

        location = get_location()
        if location:
            sensor_annotation_md["core:latitude"] = (location.latitude, )
            sensor_annotation_md["core:longitude"] = location.longitude

        sigmf_md.add_annotation(start_index=0,
                                length=num_samples,
                                metadata=sensor_annotation_md)

        return sigmf_md
Exemplo n.º 11
0
    def acquire_samples(self, n, nskip=0, retries=5):  # -> np.ndarray:
        """Aquire nskip+n samples and return the last n"""
        self.sigan_overload = False
        self.capture_time = None

        # Get the calibration data for the acquisition
        self.recompute_calibration_data()

        # Compute the linear gain
        db_gain = self.sensor_calibration_data["gain_sensor"]
        linear_gain = 10 ** (db_gain / 20.0)

        # Try to acquire the samples
        max_retries = retries
        while True:
            # No need to skip initial samples when simulating the radio
            if settings.MOCK_RADIO:
                nsamps = n
            else:
                nsamps = n + nskip

            self.capture_time = utils.get_datetime_str_now()
            samples = self.usrp.recv_num_samps(
                nsamps,  # number of samples
                self.frequency,  # center frequency in Hz
                self.sample_rate,  # sample rate in samples per second
                [0],  # channel list
                self.gain,  # gain in dB
            )
            # usrp.recv_num_samps returns a numpy array of shape
            # (n_channels, n_samples) and dtype complex64
            assert samples.dtype == np.complex64
            assert len(samples.shape) == 2 and samples.shape[0] == 1
            data = samples[0]  # isolate data for channel 0
            data_len = len(data)

            if not settings.MOCK_RADIO:
                data = data[nskip:]

            if not len(data) == n:
                if retries > 0:
                    msg = "USRP error: requested {} samples, but got {}."
                    logger.warning(msg.format(n + nskip, data_len))
                    logger.warning("Retrying {} more times.".format(retries))
                    retries = retries - 1
                else:
                    err = "Failed to acquire correct number of samples "
                    err += "{} times in a row.".format(max_retries)
                    raise RuntimeError(err)
            else:
                logger.debug("Successfully acquired {} samples.".format(n))

                # Check IQ values versus ADC max for sigan compression
                self.sigan_overload = False
                i_samples = np.abs(np.real(data))
                q_samples = np.abs(np.imag(data))
                i_over_threshold = np.sum(i_samples > self.ADC_FULL_RANGE_THRESHOLD)
                q_over_threshold = np.sum(q_samples > self.ADC_FULL_RANGE_THRESHOLD)
                total_over_threshold = i_over_threshold + q_over_threshold
                ratio_over_threshold = float(total_over_threshold) / n
                if ratio_over_threshold > self.ADC_OVERLOAD_THRESHOLD:
                    self.sigan_overload = True

                # Scale the data back to RF power and return it
                data /= linear_gain
                return data
    def build_sigmf_md(self, task_id, data):
        logger.debug("Building SigMF metadata file")

        # Use the radio's actual reported sample rate instead of requested rate
        sample_rate = self.sdr.radio.sample_rate

        sigmf_md = SigMFFile()
        sigmf_md.set_global_info(GLOBAL_INFO)
        sigmf_md.set_global_field("core:sample_rate", sample_rate)

        sensor_def = capabilities["sensor_definition"]
        sensor_def["id"] = settings.FQDN
        sigmf_md.set_global_field("ntia-sensor:sensor", sensor_def)

        action_def = {
            "name": self.name,
            "description": self.description,
            "type": ["FrequencyDomain"],
        }

        sigmf_md.set_global_field("ntia-scos:action", action_def)
        sigmf_md.set_global_field("ntia-scos:task_id", task_id)

        capture_md = {
            "core:frequency": self.sdr.radio.frequency,
            "core:datetime": utils.get_datetime_str_now(),
        }

        sigmf_md.add_capture(start_index=0, metadata=capture_md)

        for i, detector in enumerate(M4sDetector):
            frequency_domain_detection_md = {
                "ntia-core:annotation_type":
                "FrequencyDomainDetection",
                "ntia-algorithm:number_of_samples_in_fft":
                self.measurement_params.fft_size,
                "ntia-algorithm:window":
                "flattop",
                "ntia-algorithm:equivalent_noise_bandwidth":
                self.enbw,
                "ntia-algorithm:detector":
                detector.name + "_power",
                "ntia-algorithm:number_of_ffts":
                self.measurement_params.num_ffts,
                "ntia-algorithm:units":
                "dBm",
                "ntia-algorithm:reference":
                "not referenced",
                "nita-algorithm:detection_domain":
                "frequency",
            }

            sigmf_md.add_annotation(
                start_index=(i * self.measurement_params.fft_size),
                length=self.measurement_params.fft_size,
                metadata=frequency_domain_detection_md,
            )

        calibration_annotation_md = self.sdr.radio.create_calibration_annotation(
        )
        sigmf_md.add_annotation(
            start_index=0,
            length=self.measurement_params.fft_size * len(M4sDetector),
            metadata=calibration_annotation_md,
        )

        # Recover the sigan overload flag
        sigan_overload = self.sdr.radio.sigan_overload

        # Check time domain average power versus calibrated compression
        flattened_data = data.flatten()
        time_domain_avg_power = 10 * np.log10(
            np.mean(np.abs(flattened_data)**2))
        time_domain_avg_power += (10 * np.log10(1 / (2 * 50)) + 30
                                  )  # Convert log(V^2) to dBm
        sensor_overload = (
            time_domain_avg_power >
            self.sdr.radio.sensor_calibration_data["1db_compression_sensor"])

        # Create SensorAnnotation and add gain setting and overload indicators
        sensor_annotation_md = {
            "ntia-core:annotation_type": "SensorAnnotation",
            "ntia-sensor:overload_sensor": sensor_overload,
            "ntia-sensor:overload_sigan": sigan_overload,
            "ntia-sensor:gain_setting_sigan": self.measurement_params.gain,
        }

        location = get_location()
        if location:
            sensor_annotation_md["core:latitude"] = (location.latitude, )
            sensor_annotation_md["core:longitude"] = location.longitude

        sigmf_md.add_annotation(
            start_index=0,
            length=self.measurement_params.fft_size * len(M4sDetector),
            metadata=sensor_annotation_md,
        )

        return sigmf_md