""" Модели параметров сигнала (Parameter, SigmaParameter). """ from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import ExpressionWrapper, F from .defaults import ( get_default_polarization, get_default_modulation, get_default_standard, ) class Parameter(models.Model): id_satellite = models.ForeignKey( 'mainapp.Satellite', on_delete=models.PROTECT, related_name="parameters", verbose_name="Спутник", null=True, ) polarization = models.ForeignKey( 'mainapp.Polarization', default=get_default_polarization, on_delete=models.SET_DEFAULT, related_name="polarizations", null=True, blank=True, verbose_name="Поляризация", ) frequency = models.FloatField( default=0, null=True, blank=True, verbose_name="Частота, МГц", db_index=True, help_text="Центральная частота сигнала", ) freq_range = models.FloatField( default=0, null=True, blank=True, verbose_name="Полоса частот, МГц", help_text="Полоса частот сигнала", ) bod_velocity = models.FloatField( default=0, null=True, blank=True, verbose_name="Символьная скорость, БОД", help_text="Символьная скорость должна быть положительной", ) modulation = models.ForeignKey( 'mainapp.Modulation', default=get_default_modulation, on_delete=models.SET_DEFAULT, related_name="modulations", null=True, blank=True, verbose_name="Модуляция", ) snr = models.FloatField( default=0, null=True, blank=True, verbose_name="ОСШ", help_text="Отношение сигнал/шум", ) standard = models.ForeignKey( 'mainapp.Standard', default=get_default_standard, on_delete=models.SET_DEFAULT, related_name="standards", null=True, blank=True, verbose_name="Стандарт", ) objitem = models.OneToOneField( 'mainapp.ObjItem', on_delete=models.CASCADE, related_name="parameter_obj", verbose_name="Объект", null=True, blank=True, help_text="Связанный объект", ) def clean(self): """Валидация на уровне модели""" super().clean() # Проверка что частота больше полосы частот if self.frequency and self.freq_range: if self.freq_range > self.frequency: raise ValidationError( {"freq_range": "Полоса частот не может быть больше частоты"} ) # Проверка что символьная скорость соответствует полосе частот if self.bod_velocity and self.freq_range: if self.bod_velocity > self.freq_range * 1000000: # Конвертация МГц в Гц raise ValidationError( { "bod_velocity": "Символьная скорость не может превышать полосу частот" } ) def __str__(self): polarization_name = self.polarization.name if self.polarization else "-" modulation_name = self.modulation.name if self.modulation else "-" return f"Источник-{self.frequency}:{self.freq_range} МГц:{polarization_name}:{modulation_name}" class Meta: verbose_name = "ВЧ загрузка" verbose_name_plural = "ВЧ загрузки" indexes = [ models.Index(fields=["id_satellite", "frequency"]), models.Index(fields=["frequency", "polarization"]), ] class SigmaParameter(models.Model): TRANSFERS = [(-1.0, "-"), (9750.0, "9750 МГц"), (10750.0, "10750 МГц")] id_satellite = models.ForeignKey( 'mainapp.Satellite', on_delete=models.PROTECT, related_name="sigmapar_sat", verbose_name="Спутник", ) transfer = models.FloatField( choices=TRANSFERS, default=-1.0, verbose_name="Перенос по частоте", help_text="Выберите перенос по частоте", ) status = models.CharField( max_length=20, blank=True, null=True, verbose_name="Статус", help_text="Статус измерения", ) frequency = models.FloatField( default=0, null=True, blank=True, verbose_name="Частота, МГц", db_index=True, help_text="Центральная частота сигнала", ) transfer_frequency = models.GeneratedField( expression=ExpressionWrapper( F("frequency") + F("transfer"), output_field=models.FloatField() ), output_field=models.FloatField(), db_persist=True, null=True, blank=True, verbose_name="Частота в Ku, МГц", ) freq_range = models.FloatField( default=0, null=True, blank=True, verbose_name="Полоса частот, МГц", help_text="Полоса частот", ) power = models.FloatField( default=0, null=True, blank=True, verbose_name="Мощность, дБм", help_text="Мощность сигнала", ) bod_velocity = models.FloatField( default=0, null=True, blank=True, verbose_name="Символьная скорость, БОД", help_text="Символьная скорость должна быть положительной", ) polarization = models.ForeignKey( 'mainapp.Polarization', default=get_default_polarization, on_delete=models.SET_DEFAULT, related_name="polarizations_sigma", null=True, blank=True, verbose_name="Поляризация", ) modulation = models.ForeignKey( 'mainapp.Modulation', default=get_default_modulation, on_delete=models.SET_DEFAULT, related_name="modulations_sigma", null=True, blank=True, verbose_name="Модуляция", ) snr = models.FloatField( default=0, null=True, blank=True, verbose_name="ОСШ, Дб", validators=[MinValueValidator(-50), MaxValueValidator(100)], help_text="Отношение сигнал/шум в диапазоне от -50 до 100 дБ", ) standard = models.ForeignKey( 'mainapp.Standard', default=get_default_standard, on_delete=models.SET_DEFAULT, related_name="standards_sigma", null=True, blank=True, verbose_name="Стандарт", ) packets = models.BooleanField( null=True, blank=True, verbose_name="Пакетность", help_text="Наличие пакетной передачи", ) datetime_begin = models.DateTimeField( null=True, blank=True, verbose_name="Время начала измерения", help_text="Дата и время начала измерения", ) datetime_end = models.DateTimeField( null=True, blank=True, verbose_name="Время окончания измерения", help_text="Дата и время окончания измерения", ) parameter = models.ForeignKey( 'mainapp.Parameter', on_delete=models.SET_NULL, related_name="sigma_parameter", verbose_name="ВЧ", null=True, blank=True, ) def clean(self): """Валидация на уровне модели""" super().clean() # Проверка что время окончания больше времени начала if self.datetime_begin and self.datetime_end: if self.datetime_end < self.datetime_begin: raise ValidationError( {"datetime_end": "Время окончания должно быть позже времени начала"} ) # Проверка что частота больше полосы частот if self.frequency and self.freq_range: if self.freq_range > self.frequency: raise ValidationError( {"freq_range": "Полоса частот не может быть больше частоты"} ) def __str__(self): modulation_name = self.modulation.name if self.modulation else "-" return f"Sigma-{self.frequency}:{self.freq_range} МГц:{modulation_name}" class Meta: verbose_name = "ВЧ sigma" verbose_name_plural = "ВЧ sigma"