This commit is contained in:
2026-04-04 01:16:16 +03:30
parent ecb42c6895
commit 6d5ece1f5d
22 changed files with 311 additions and 261 deletions
+50
View File
@@ -0,0 +1,50 @@
from sensor_catalog.models import SensorCatalog
SENSOR_CATALOG_ITEMS = [
{
"code": "sensor_7_soil_moisture_sensor_v1_2",
"name": "Sensor 7 - Soil Moisture Sensor v1.2",
"description": (
"This sensor is typically the YL-69 or FC-28 soil moisture sensor. "
"It measures only soil moisture and provides analog and digital outputs. "
"It does not report soil temperature, pH, or nutrients."
),
"customizable_fields": [],
"supported_power_sources": ["solar", "direct_power"],
"returned_data_fields": ["soil_moisture", "analog_output", "digital_output"],
"sample_payload": {
"soil_moisture": 42,
"analog_output": 610,
"digital_output": 1,
},
"is_active": True,
}
]
def seed_sensor_catalog():
created_count = 0
updated_count = 0
results = []
for item in SENSOR_CATALOG_ITEMS:
sensor, created = SensorCatalog.objects.update_or_create(
code=item["code"],
defaults={
"name": item["name"],
"description": item["description"],
"customizable_fields": item["customizable_fields"],
"supported_power_sources": item["supported_power_sources"],
"returned_data_fields": item["returned_data_fields"],
"sample_payload": item["sample_payload"],
"is_active": item["is_active"],
},
)
results.append((sensor, created))
if created:
created_count += 1
else:
updated_count += 1
return results, created_count, updated_count
@@ -1,53 +1,17 @@
from django.core.management.base import BaseCommand
from sensor_catalog.models import SensorCatalog
SENSOR_CATALOG_ITEMS = [
{
"name": "Sensor 7 - Soil Moisture Sensor v1.2",
"description": (
"This sensor is typically the YL-69 or FC-28 soil moisture sensor. "
"It measures only soil moisture and provides analog and digital outputs. "
"It does not report soil temperature, pH, or nutrients."
),
"customizable_fields": [],
"supported_power_sources": ["solar", "direct_power"],
"returned_data_fields": ["soil_moisture", "analog_output", "digital_output"],
"sample_payload": {
"soil_moisture": 42,
"analog_output": 610,
"digital_output": 1,
},
"is_active": True,
}
]
from sensor_catalog.management import seed_sensor_catalog
class Command(BaseCommand):
help = "Seed sensor catalog data."
def handle(self, *args, **options):
created_count = 0
updated_count = 0
for item in SENSOR_CATALOG_ITEMS:
sensor, created = SensorCatalog.objects.update_or_create(
name=item["name"],
defaults={
"description": item["description"],
"customizable_fields": item["customizable_fields"],
"supported_power_sources": item["supported_power_sources"],
"returned_data_fields": item["returned_data_fields"],
"sample_payload": item["sample_payload"],
"is_active": item["is_active"],
},
)
results, created_count, updated_count = seed_sensor_catalog()
for sensor, created in results:
if created:
created_count += 1
self.stdout.write(self.style.SUCCESS(f"Created sensor catalog item: {sensor.name}"))
else:
updated_count += 1
self.stdout.write(self.style.WARNING(f"Updated sensor catalog item: {sensor.name}"))
self.stdout.write(
@@ -0,0 +1,44 @@
import re
from django.db import migrations, models
def _to_snake_case(value):
normalized = re.sub(r"[^a-zA-Z0-9]+", "_", (value or "").strip()).strip("_").lower()
return normalized or "sensor"
def populate_sensor_codes(apps, schema_editor):
SensorCatalog = apps.get_model("sensor_catalog", "SensorCatalog")
used_codes = set()
for sensor in SensorCatalog.objects.all().order_by("id"):
base_code = _to_snake_case(sensor.name)
code = base_code
suffix = 2
while code in used_codes:
code = f"{base_code}_{suffix}"
suffix += 1
sensor.code = code
sensor.save(update_fields=["code"])
used_codes.add(code)
class Migration(migrations.Migration):
dependencies = [
("sensor_catalog", "0002_sensorcatalog_supported_power_sources"),
]
operations = [
migrations.AddField(
model_name="sensorcatalog",
name="code",
field=models.CharField(blank=True, db_index=True, default="", max_length=255),
),
migrations.RunPython(populate_sensor_codes, migrations.RunPython.noop),
migrations.AlterField(
model_name="sensorcatalog",
name="code",
field=models.CharField(db_index=True, max_length=255, unique=True),
),
]
+2 -1
View File
@@ -5,6 +5,7 @@ from django.db import models
class SensorCatalog(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, db_index=True)
code = models.CharField(max_length=255, unique=True, db_index=True)
name = models.CharField(max_length=255, unique=True, db_index=True)
description = models.TextField(blank=True, default="")
customizable_fields = models.JSONField(default=list, blank=True)
@@ -17,7 +18,7 @@ class SensorCatalog(models.Model):
class Meta:
db_table = "sensor_catalogs"
ordering = ["name"]
ordering = ["code"]
def __str__(self):
return self.name
+1
View File
@@ -8,6 +8,7 @@ class SensorCatalogSerializer(serializers.ModelSerializer):
model = SensorCatalog
fields = [
"uuid",
"code",
"name",
"description",
"customizable_fields",
+4 -2
View File
@@ -16,6 +16,7 @@ class SensorCatalogListViewTests(TestCase):
phone_number="09120000002",
)
SensorCatalog.objects.update_or_create(
code="sensor_7_soil_moisture_sensor_v1_2",
name="Sensor 7 - Soil Moisture Sensor v1.2",
defaults={
"description": (
@@ -30,6 +31,7 @@ class SensorCatalogListViewTests(TestCase):
},
)
SensorCatalog.objects.update_or_create(
code="legacy_sensor",
name="Legacy Sensor",
defaults={
"customizable_fields": [],
@@ -50,6 +52,6 @@ class SensorCatalogListViewTests(TestCase):
self.assertEqual(response.data["code"], 200)
self.assertEqual(len(response.data["data"]), 2)
self.assertEqual(
{item["name"] for item in response.data["data"]},
{"Sensor 7 - Soil Moisture Sensor v1.2", "Legacy Sensor"},
{item["code"] for item in response.data["data"]},
{"sensor_7_soil_moisture_sensor_v1_2", "legacy_sensor"},
)
+1 -1
View File
@@ -17,6 +17,6 @@ class SensorCatalogListView(APIView):
responses={200: code_response("SensorCatalogListResponse", data=SensorCatalogSerializer(many=True))},
)
def get(self, request):
sensors = SensorCatalog.objects.order_by("name")
sensors = SensorCatalog.objects.order_by("code")
data = SensorCatalogSerializer(sensors, many=True).data
return Response({"code": 200, "msg": "success", "data": data}, status=status.HTTP_200_OK)