from django.db import models from django.contrib.auth.models import User from django.contrib.gis.db import models as gis from django.contrib.gis.db.models import functions from django.db.models import F, ExpressionWrapper def get_default_polarization(): obj, created = Polarization.objects.get_or_create( name="-" ) return obj.id def get_default_modulation(): obj, created = Modulation.objects.get_or_create( name="-" ) return obj.id def get_default_standard(): obj, created = Standard.objects.get_or_create( name="-" ) return obj.id class CustomUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) ROLE_CHOICES = [ ('admin', 'Администратор'), ('moderator', 'Модератор'), ('user', 'Пользователь'), ] role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user', verbose_name='Роль пользователя') def __str__(self): return f"{self.user.first_name} {self.user.last_name}" if self.user.first_name and self.user.last_name else self.user.username class Meta: verbose_name = "Пользователь" verbose_name_plural = "Пользователи" class SigmaParMark(models.Model): mark = models.BooleanField(null=True, blank=True, verbose_name="Наличие сигнала") timestamp = models.DateTimeField(null=True, blank=True, verbose_name="Время") def __str__(self): timestamp = self.timestamp.strftime("%d.%m.%Y %H:%M") return f'+ {timestamp}' if self.mark else f'- {timestamp}' class Meta: verbose_name = "Отметка" verbose_name_plural = "Отметки" class Mirror(models.Model): name = models.CharField(max_length=30, unique=True, verbose_name="Имя зеркала") def __str__(self): return self.name class Meta: verbose_name = "Зеркало" verbose_name_plural = "Зеркала" class Polarization(models.Model): name = models.CharField(max_length=20, unique=True, verbose_name="Поляризация") def __str__(self): return self.name class Meta: verbose_name = "Поляризация" verbose_name_plural = "Поляризация" class Modulation(models.Model): name = models.CharField(max_length=20, unique=True, verbose_name="Модуляция", db_index=True) def __str__(self): return self.name class Meta: verbose_name = "Модуляция" verbose_name_plural = "Модуляции" class Standard(models.Model): name = models.CharField(max_length=20, unique=True, verbose_name="Стандарт") def __str__(self): return self.name class Meta: verbose_name = "Стандарт" verbose_name_plural = "Стандарты" class Satellite(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name="Имя спутника", db_index=True) norad = models.IntegerField(blank=True, null=True, verbose_name="NORAD ID") def __str__(self): return self.name class Meta: verbose_name = "Спутник" verbose_name_plural = "Спутники" class ObjItem(models.Model): name = models.CharField(null=True, blank=True, max_length=100, verbose_name="Имя объекта", db_index=True) # id_satellite = models.ForeignKey(Satellite, on_delete=models.PROTECT, related_name="objitems", verbose_name="Спутник") # id_vch_load = models.ForeignKey(Parameter, on_delete=models.CASCADE, related_name="objitems", verbose_name="ВЧ загрузка") # id_geo = models.ForeignKey(Geo, on_delete=models.CASCADE, related_name="objitems", verbose_name="Геоданные") id_user_add = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="objitems", verbose_name="Пользователь", null=True, blank=True) # id_source_type = models.ForeignKey(SourceType, on_delete=models.SET_NULL, related_name="objitems", verbose_name='Тип источника', null=True, blank=True) def __str__(self): return f"Объект {self.name}" class Meta: verbose_name = "Объект" verbose_name_plural = "Объекты" # constraints = [ # models.UniqueConstraint( # fields=['id_vch_load', 'id_geo'], # name='unique_objitem_combination' # ) # ] class SourceType(models.Model): name = models.CharField(max_length=50, unique=True, verbose_name="Тип источника") objitem = models.OneToOneField(ObjItem, on_delete=models.SET_NULL, verbose_name="Гео", related_name="source_type_obj", null=True) def __str__(self): return self.name class Meta: verbose_name = "Тип источника" verbose_name_plural = 'Типы источников' class Parameter(models.Model): id_satellite = models.ForeignKey(Satellite, on_delete=models.PROTECT, related_name="parameters", verbose_name="Спутник", null=True) polarization = models.ForeignKey( 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) freq_range = models.FloatField(default=0, null=True, blank=True, verbose_name="Полоса частот, МГц") bod_velocity = models.FloatField(default=0, null=True, blank=True, verbose_name="Символьная скорость, БОД") modulation = models.ForeignKey( 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="ОСШ") standard = models.ForeignKey( Standard, default=get_default_standard, on_delete=models.SET_DEFAULT, related_name="standards", null=True, blank=True, verbose_name="Стандарт" ) id_user_add = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="parameter_added", verbose_name="Пользователь", null=True, blank=True) objitems = models.ManyToManyField(ObjItem, related_name="parameters_obj", verbose_name="Источники", blank=True) # id_sigma_parameter = models.ManyToManyField(SigmaParameter, on_delete=models.SET_NULL, related_name="sigma_parameter", verbose_name="ВЧ с sigma", null=True, blank=True) # id_sigma_parameter = models.ManyToManyField(SigmaParameter, verbose_name="ВЧ с sigma", null=True, blank=True) 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']), ] # constraints = [ # models.UniqueConstraint( # fields=[ # 'polarization', 'frequency', 'freq_range', # 'bod_velocity', 'modulation', 'snr', 'standard' # ], # name='unique_parameter_combination' # ) # ] class SigmaParameter(models.Model): TRANSFERS = [ (-1.0, "-"), (9750.0, "9750 МГц"), (10750.0, "10750 МГц") ] id_satellite = models.ForeignKey(Satellite, on_delete=models.PROTECT, related_name="sigmapar_sat", verbose_name="Спутник") transfer = models.FloatField( choices=TRANSFERS, default=-1.0, verbose_name="Перенос по частоте" ) status = models.CharField(max_length=20, blank=True, null=True, verbose_name="Статус") frequency = models.FloatField(default=0, null=True, blank=True, verbose_name="Частота, МГц", db_index=True) 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="Полоса частот, МГц") power = models.FloatField(default=0, null=True, blank=True, verbose_name="Мощность, дБм") bod_velocity = models.FloatField(default=0, null=True, blank=True, verbose_name="Символьная скорость, БОД") polarization = models.ForeignKey( Polarization, default=get_default_polarization, on_delete=models.SET_DEFAULT, related_name="polarizations_sigma", null=True, blank=True, verbose_name="Поляризация" ) modulation = models.ForeignKey( 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="ОСШ, Дб") standard = models.ForeignKey( 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="Пакетность") datetime_begin = models.DateTimeField(null=True, blank=True, verbose_name="Время начала измерения") datetime_end = models.DateTimeField(null=True, blank=True, verbose_name="Время окончания измерения") mark = models.ManyToManyField(SigmaParMark, verbose_name="Отметка", blank=True) parameter = models.ForeignKey( Parameter, on_delete=models.SET_NULL, related_name='sigma_parameter', verbose_name="ВЧ", null=True, blank=True ) 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" class Geo(models.Model): mirrors = models.ManyToManyField(Mirror, related_name="geo_mirrors", verbose_name="Зеркала",) timestamp = models.DateTimeField(null=True, blank=True, verbose_name="Время", db_index=True) coords = gis.PointField(srid=4326, null=True, blank=True, verbose_name="Координата геолокации") location = models.CharField(max_length=255, null=True, blank=True, verbose_name="Метоположение") comment = models.CharField(max_length=255, blank=True, verbose_name="Комментарий") coords_kupsat = gis.PointField(srid=4326, null=True, blank=True, verbose_name="Координаты Кубсата") coords_valid = gis.PointField(srid=4326, null=True, blank=True, verbose_name="Координаты оперативников") is_average = models.BooleanField(null=True, blank=True, verbose_name="Усреднённое") id_user_add = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="geos_added", verbose_name="Пользователь", null=True, blank=True) distance_coords_kup = models.GeneratedField( expression=functions.Distance("coords", "coords_kupsat")/1000, output_field=models.FloatField(), db_persist=True, null=True, blank=True, verbose_name="Расстояние между купсатом и гео, км" ) distance_coords_valid = models.GeneratedField( expression=functions.Distance("coords", "coords_valid")/1000, output_field=models.FloatField(), db_persist=True, null=True, blank=True, verbose_name="Расстояние между гео и оперативным отделом, км" ) distance_kup_valid = models.GeneratedField( expression=functions.Distance("coords_valid", "coords_kupsat")/1000, output_field=models.FloatField(), db_persist=True, null=True, blank=True, verbose_name="Расстояние между купсатом и оперативным отделом, км" ) objitem = models.OneToOneField(ObjItem, on_delete=models.SET_NULL, verbose_name="Гео", related_name="geo_obj", null=True) def __str__(self): longitude = self.coords.coords[0] latitude = self.coords.coords[1] lon = f"{longitude}E" if longitude > 0 else f"{abs(longitude)}W" lat = f"{latitude}N" if latitude > 0 else f"{abs(latitude)}S" return f"{lat} {lon}, {self.location}" class Meta: verbose_name = "Гео" verbose_name_plural = "Гео" constraints = [ models.UniqueConstraint( fields=[ 'timestamp', 'coords' ], name='unique_geo_combination' ) ]