fix / add logger fields to db tables
This commit is contained in:
12
backend/Pipfile.lock
generated
12
backend/Pipfile.lock
generated
@@ -26,12 +26,12 @@
|
||||
},
|
||||
"django": {
|
||||
"hashes": [
|
||||
"sha256:60c35bd96201b10c6e7a78121bd0da51084733efa303cc19ead021ab179cef5e",
|
||||
"sha256:a1228c384f8fa13eebc015196db7b3e08722c5058d4758d20cb287503a540d8f"
|
||||
"sha256:0745b25681b129a77aae3d4f6549b62d3913d74407831abaa0d9021a03954bae",
|
||||
"sha256:2b2ada0ee8a5ff743a40e2b9820d1f8e24c11bac9ae6469cd548f0057ea6ddcd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.10'",
|
||||
"version": "==5.2.4"
|
||||
"version": "==5.2.5"
|
||||
},
|
||||
"django-cors-headers": {
|
||||
"hashes": [
|
||||
@@ -44,12 +44,12 @@
|
||||
},
|
||||
"djangorestframework": {
|
||||
"hashes": [
|
||||
"sha256:bea7e9f6b96a8584c5224bfb2e4348dfb3f8b5e34edbecb98da258e892089361",
|
||||
"sha256:f022ff46613584de994c0c6a4aebbace5fd700555fbe9d33b865ebf173eba6c9"
|
||||
"sha256:166809528b1aced0a17dc66c24492af18049f2c9420dbd0be29422029cfc3ff7",
|
||||
"sha256:33a59f47fb9c85ede792cbf88bde71893bcda0667bc573f784649521f1102cec"
|
||||
],
|
||||
"index": "pypi",
|
||||
"markers": "python_version >= '3.9'",
|
||||
"version": "==3.16.0"
|
||||
"version": "==3.16.1"
|
||||
},
|
||||
"dotenv": {
|
||||
"hashes": [
|
||||
|
||||
0
backend/api/parser/__init__.py
Normal file
0
backend/api/parser/__init__.py
Normal file
0
backend/api/parser/serializers.py
Normal file
0
backend/api/parser/serializers.py
Normal file
0
backend/api/parser/views.py
Normal file
0
backend/api/parser/views.py
Normal file
@@ -1,7 +1,7 @@
|
||||
asgiref==3.9.1
|
||||
Django==5.2.4
|
||||
Django==5.2.5
|
||||
django-cors-headers==4.7.0
|
||||
djangorestframework==3.16.0
|
||||
djangorestframework==3.16.1
|
||||
dotenv==0.9.9
|
||||
iniconfig==2.1.0
|
||||
packaging==25.0
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
from django.contrib import admin
|
||||
from .models import Multiplexor, Channel, SensorType, SignalFormat, Sensor, Metric, Alert
|
||||
|
||||
# Register your models here.
|
||||
@admin.register(Multiplexor)
|
||||
class MultiplexorAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'ip', 'subnet', 'gateway', 'sd_path')
|
||||
|
||||
@admin.register(Channel)
|
||||
class ChannelAdmin(admin.ModelAdmin):
|
||||
list_display = ('multiplexor', 'number', 'position')
|
||||
|
||||
@admin.register(SensorType)
|
||||
class SensorTypeAdmin(admin.ModelAdmin):
|
||||
list_display = ('code', 'name', 'description')
|
||||
|
||||
|
||||
@admin.register(Metric)
|
||||
class MetricAdmin(admin.ModelAdmin):
|
||||
list_display = ('timestamp', 'sensor', 'raw_value', 'value', 'status')
|
||||
|
||||
@admin.register(Alert)
|
||||
class AlertAdmin(admin.ModelAdmin):
|
||||
list_display = ('sensor', 'metric', 'sensor_type', 'message', 'severity', 'created_at', 'resolved')
|
||||
|
||||
@admin.register(SignalFormat)
|
||||
class SignalFormatAdmin(admin.ModelAdmin):
|
||||
list_display = ('sensor_type', 'code', 'unit', 'conversion_rule')
|
||||
|
||||
@admin.register(Sensor)
|
||||
class SensorAdmin(admin.ModelAdmin):
|
||||
list_display = ('channel', 'sensor_type', 'signal_format', 'serial_number', 'name')
|
||||
@@ -0,0 +1,121 @@
|
||||
# Generated by Django 5.2.5 on 2025-08-25 07:41
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sitemanagement', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='alert',
|
||||
options={'ordering': ['created_at', 'sensor'], 'verbose_name': 'Тревога', 'verbose_name_plural': 'Тревоги'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='channel',
|
||||
options={'ordering': ['multiplexor', 'number', 'position'], 'verbose_name': 'Канал', 'verbose_name_plural': 'Каналы'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='metric',
|
||||
options={'ordering': ['timestamp', 'sensor'], 'verbose_name': 'Метрика', 'verbose_name_plural': 'Метрики'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='multiplexor',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Мультиплексор', 'verbose_name_plural': 'Мультиплексоры'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='sensor',
|
||||
options={'ordering': ['channel', 'sensor_type', 'serial_number'], 'verbose_name': 'Датчик', 'verbose_name_plural': 'Датчики'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='sensortype',
|
||||
options={'ordering': ['name'], 'verbose_name': 'Тип сенсора', 'verbose_name_plural': 'Типы сенсоров'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='signalformat',
|
||||
options={'ordering': ['sensor_type', 'code'], 'verbose_name': 'Формат сигнала', 'verbose_name_plural': 'Форматы сигналов'},
|
||||
),
|
||||
migrations.RemoveIndex(
|
||||
model_name='metric',
|
||||
name='sitemanagem_timesta_ac22b7_idx',
|
||||
),
|
||||
migrations.RemoveIndex(
|
||||
model_name='metric',
|
||||
name='sitemanagem_sensor__8d94ff_idx',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='alert',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='channel',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='channel',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='metric',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='metric',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='multiplexor',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='multiplexor',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sensor',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sensor',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sensortype',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='sensortype',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='signalformat',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='signalformat',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True),
|
||||
),
|
||||
]
|
||||
@@ -9,6 +9,12 @@ class Multiplexor(models.Model):
|
||||
subnet = models.GenericIPAddressField(null=True, blank=True)
|
||||
gateway = models.GenericIPAddressField(null=True, blank=True)
|
||||
sd_path = models.CharField(max_length=255, null=True, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
class Meta:
|
||||
verbose_name = "Мультиплексор"
|
||||
verbose_name_plural = "Мультиплексоры"
|
||||
ordering = ["name"]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -20,10 +26,14 @@ class Channel(models.Model):
|
||||
number = models.PositiveSmallIntegerField() # CH-1 ... CH-14
|
||||
# для "полканалов" можно использовать дробное значение (1, 1.5, 2, ...)
|
||||
position = models.DecimalField(max_digits=4, decimal_places=1, default=Decimal("1.0"))
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
class Meta:
|
||||
unique_together = ("multiplexor", "number", "position")
|
||||
|
||||
verbose_name = "Канал"
|
||||
verbose_name_plural = "Каналы"
|
||||
ordering = ["multiplexor", "number", "position"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.multiplexor.name} - CH{self.number} ({self.position})"
|
||||
|
||||
@@ -33,10 +43,16 @@ class SensorType(models.Model):
|
||||
code = models.CharField(max_length=10, unique=True) # GA, PE, GLE
|
||||
name = models.CharField(max_length=100)
|
||||
description = models.TextField(blank=True, null=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
# пороговые значения для всех сенсоров этого типа
|
||||
min_value = models.DecimalField(max_digits=12, decimal_places=4, null=True, blank=True)
|
||||
max_value = models.DecimalField(max_digits=12, decimal_places=4, null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Тип сенсора"
|
||||
verbose_name_plural = "Типы сенсоров"
|
||||
ordering = ["name"]
|
||||
|
||||
def __str__(self):
|
||||
return self.code
|
||||
@@ -48,10 +64,14 @@ class SignalFormat(models.Model):
|
||||
code = models.CharField(max_length=50) # например "4-20мА", "VW f<1600Hz", "NTC R>250Ohm"
|
||||
unit = models.CharField(max_length=20, blank=True, null=True) # °C, мкм/м, мм и т.п.
|
||||
conversion_rule = models.CharField(max_length=255, blank=True, null=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
class Meta:
|
||||
unique_together = ("sensor_type", "code")
|
||||
|
||||
verbose_name = "Формат сигнала"
|
||||
verbose_name_plural = "Форматы сигналов"
|
||||
ordering = ["sensor_type", "code"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.sensor_type.code} - {self.code}"
|
||||
|
||||
@@ -63,6 +83,12 @@ class Sensor(models.Model):
|
||||
signal_format = models.ForeignKey(SignalFormat, on_delete=models.SET_NULL, null=True, blank=True)
|
||||
serial_number = models.CharField(max_length=50, blank=True, null=True) # CL 2106009
|
||||
name = models.CharField(max_length=50, blank=True, null=True) # GA-1, HLE-1 и т.п.
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
class Meta:
|
||||
verbose_name = "Датчик"
|
||||
verbose_name_plural = "Датчики"
|
||||
ordering = ["channel", "sensor_type", "serial_number"]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name or self.sensor_type.code} ({self.serial_number})"
|
||||
@@ -75,13 +101,18 @@ class Metric(models.Model):
|
||||
raw_value = models.CharField(max_length=50) # исходное значение из файла (например "11.964 (A)")
|
||||
value = models.FloatField(null=True, blank=True) # преобразованное значение
|
||||
status = models.CharField(max_length=20, blank=True, null=True) # No Rx, Error, NotAv и т.д.
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Метрика"
|
||||
verbose_name_plural = "Метрики"
|
||||
ordering = ["timestamp", "sensor"]
|
||||
indexes = [
|
||||
models.Index(fields=["timestamp"]),
|
||||
models.Index(fields=["sensor"]),
|
||||
]
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.timestamp} {self.sensor} = {self.value} {self.sensor.signal_format.unit if self.sensor.signal_format else ''}"
|
||||
|
||||
@@ -101,6 +132,7 @@ class Alert(models.Model):
|
||||
default="warning"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
resolved = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
@@ -109,6 +141,9 @@ class Alert(models.Model):
|
||||
models.Index(fields=["sensor"]),
|
||||
models.Index(fields=["sensor_type"]),
|
||||
]
|
||||
|
||||
verbose_name = "Тревога"
|
||||
verbose_name_plural = "Тревоги"
|
||||
ordering = ["created_at", "sensor"]
|
||||
|
||||
def __str__(self):
|
||||
return f"ALERT {self.sensor} @ {self.metric.timestamp}: {self.message}"
|
||||
Reference in New Issue
Block a user