first commit
This commit is contained in:
@@ -19,6 +19,7 @@ class SensorDataAdmin(admin.ModelAdmin):
|
||||
)
|
||||
list_filter = ("updated_at",)
|
||||
search_fields = ("uuid_sensor", "location_id")
|
||||
filter_horizontal = ("plants",)
|
||||
|
||||
|
||||
@admin.register(SensorDataHistory)
|
||||
|
||||
@@ -10,7 +10,7 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('soil_data', '0002_soildepthdata_refactor'),
|
||||
('location_data', '0002_soildepthdata_refactor'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@@ -19,7 +19,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('uuid_sensor', models.UUIDField(help_text='شناسه سنسور')),
|
||||
('location_id', models.IntegerField(help_text='location_id از soil_data')),
|
||||
('location_id', models.IntegerField(help_text='location_id از location_data')),
|
||||
('soil_moisture', models.FloatField(blank=True, null=True)),
|
||||
('soil_temperature', models.FloatField(blank=True, null=True)),
|
||||
('soil_ph', models.FloatField(blank=True, null=True)),
|
||||
@@ -63,7 +63,7 @@ class Migration(migrations.Migration):
|
||||
('potassium', models.FloatField(blank=True, help_text='پتاسیم', null=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('location', models.ForeignKey(db_column='location_id', help_text='همان location_id در soil_data', on_delete=django.db.models.deletion.CASCADE, related_name='sensor_data', to='soil_data.soillocation')),
|
||||
('location', models.ForeignKey(db_column='location_id', help_text='همان location_id در location_data', on_delete=django.db.models.deletion.CASCADE, related_name='sensor_data', to='location_data.soillocation')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'داده سنسور',
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.2.12 on 2026-03-19 15:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('plant', '0001_initial'),
|
||||
('sensor_data', '0002_seed_initial_parameters'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='sensordata',
|
||||
name='plants',
|
||||
field=models.ManyToManyField(blank=True, help_text='گیاهان مرتبط با این سنسور', related_name='sensor_data', to='plant.plant'),
|
||||
),
|
||||
]
|
||||
@@ -16,11 +16,11 @@ class SensorData(models.Model):
|
||||
help_text="شناسه یکتای سنسور",
|
||||
)
|
||||
location = models.ForeignKey(
|
||||
"soil_data.SoilLocation",
|
||||
"location_data.SoilLocation",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="sensor_data",
|
||||
db_column="location_id",
|
||||
help_text="همان location_id در soil_data",
|
||||
help_text="همان location_id از location_data",
|
||||
)
|
||||
soil_moisture = models.FloatField(null=True, blank=True, help_text="رطوبت خاک")
|
||||
soil_temperature = models.FloatField(null=True, blank=True, help_text="دما خاک")
|
||||
@@ -31,6 +31,12 @@ class SensorData(models.Model):
|
||||
nitrogen = models.FloatField(null=True, blank=True, help_text="ازت (N)")
|
||||
phosphorus = models.FloatField(null=True, blank=True, help_text="فسفر")
|
||||
potassium = models.FloatField(null=True, blank=True, help_text="پتاسیم")
|
||||
plants = models.ManyToManyField(
|
||||
"plant.Plant",
|
||||
blank=True,
|
||||
related_name="sensor_data",
|
||||
help_text="گیاهان مرتبط با این سنسور",
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
@@ -49,7 +55,7 @@ class SensorDataHistory(models.Model):
|
||||
"""
|
||||
|
||||
uuid_sensor = models.UUIDField(help_text="شناسه سنسور")
|
||||
location_id = models.IntegerField(help_text="location_id از soil_data")
|
||||
location_id = models.IntegerField(help_text="location_id از location_data")
|
||||
soil_moisture = models.FloatField(null=True, blank=True)
|
||||
soil_temperature = models.FloatField(null=True, blank=True)
|
||||
soil_ph = models.FloatField(null=True, blank=True)
|
||||
|
||||
@@ -14,11 +14,22 @@ class SensorDataUpdateSerializer(serializers.Serializer):
|
||||
nitrogen = serializers.FloatField(required=False, allow_null=True)
|
||||
phosphorus = serializers.FloatField(required=False, allow_null=True)
|
||||
potassium = serializers.FloatField(required=False, allow_null=True)
|
||||
plant_ids = serializers.ListField(
|
||||
child=serializers.IntegerField(),
|
||||
required=False,
|
||||
help_text="لیست شناسه گیاهان مرتبط",
|
||||
)
|
||||
|
||||
|
||||
class SensorDataResponseSerializer(serializers.ModelSerializer):
|
||||
"""سریالایزر خروجی برای SensorData."""
|
||||
|
||||
plant_ids = serializers.PrimaryKeyRelatedField(
|
||||
source="plants",
|
||||
many=True,
|
||||
read_only=True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = SensorData
|
||||
fields = [
|
||||
@@ -31,6 +42,7 @@ class SensorDataResponseSerializer(serializers.ModelSerializer):
|
||||
"nitrogen",
|
||||
"phosphorus",
|
||||
"potassium",
|
||||
"plant_ids",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
]
|
||||
|
||||
+84
-1
@@ -1,9 +1,16 @@
|
||||
from django.db import transaction
|
||||
from drf_spectacular.utils import (
|
||||
OpenApiExample,
|
||||
OpenApiResponse,
|
||||
extend_schema,
|
||||
inline_serializer,
|
||||
)
|
||||
from rest_framework import serializers as drf_serializers
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from soil_data.models import SoilLocation
|
||||
from location_data.models import SoilLocation
|
||||
|
||||
from .models import ParameterUpdateLog, SensorData, SensorDataHistory, SensorParameter
|
||||
from .serializers import (
|
||||
@@ -18,9 +25,47 @@ class SensorDataUpdateView(APIView):
|
||||
آپدیت داده سنسور. هنگام آپدیت، نسخه فعلی در SensorDataHistory ذخیره میشود.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["Sensor Data"],
|
||||
summary="آپدیت کامل داده سنسور",
|
||||
description="داده سنسور را بر اساس uuid_sensor آپدیت (یا ایجاد) میکند. نسخه قبلی در تاریخچه ذخیره میشود.",
|
||||
request=SensorDataUpdateSerializer,
|
||||
responses={
|
||||
200: SensorDataResponseSerializer,
|
||||
400: OpenApiResponse(description="داده نامعتبر"),
|
||||
404: OpenApiResponse(description="location_id یافت نشد"),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست",
|
||||
value={
|
||||
"location_id": 1,
|
||||
"soil_moisture": 45.2,
|
||||
"soil_temperature": 22.5,
|
||||
"soil_ph": 6.8,
|
||||
"electrical_conductivity": 1.2,
|
||||
"nitrogen": 30.0,
|
||||
"phosphorus": 15.0,
|
||||
"potassium": 20.0,
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def put(self, request, uuid_sensor):
|
||||
return self._update(request, uuid_sensor)
|
||||
|
||||
@extend_schema(
|
||||
tags=["Sensor Data"],
|
||||
summary="آپدیت جزئی داده سنسور",
|
||||
description="فقط فیلدهای ارسالشده آپدیت میشوند.",
|
||||
request=SensorDataUpdateSerializer,
|
||||
responses={
|
||||
200: SensorDataResponseSerializer,
|
||||
400: OpenApiResponse(description="داده نامعتبر"),
|
||||
404: OpenApiResponse(description="location_id یافت نشد"),
|
||||
},
|
||||
)
|
||||
def patch(self, request, uuid_sensor):
|
||||
return self._update(request, uuid_sensor, partial=True)
|
||||
|
||||
@@ -35,6 +80,7 @@ class SensorDataUpdateView(APIView):
|
||||
)
|
||||
|
||||
location_id = serializer.validated_data.pop("location_id")
|
||||
plant_ids = serializer.validated_data.pop("plant_ids", None)
|
||||
location = SoilLocation.objects.filter(pk=location_id).first()
|
||||
if not location:
|
||||
return Response(
|
||||
@@ -67,6 +113,9 @@ class SensorDataUpdateView(APIView):
|
||||
potassium=sensor_data.potassium,
|
||||
)
|
||||
|
||||
if plant_ids is not None:
|
||||
sensor_data.plants.set(plant_ids)
|
||||
|
||||
return Response(
|
||||
{
|
||||
"code": 200,
|
||||
@@ -82,6 +131,40 @@ class SensorParameterCreateView(APIView):
|
||||
اضافه کردن پارامتر جدید و ثبت در ParameterUpdateLog.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["Sensor Parameters"],
|
||||
summary="افزودن/ویرایش پارامتر سنسور",
|
||||
description="پارامتر جدید اضافه یا پارامتر موجود را ویرایش میکند و در لاگ ثبت میشود.",
|
||||
request=SensorParameterSerializer,
|
||||
responses={
|
||||
201: inline_serializer(
|
||||
name="SensorParameterResponse",
|
||||
fields={
|
||||
"code": drf_serializers.IntegerField(),
|
||||
"msg": drf_serializers.CharField(),
|
||||
"data": inline_serializer(
|
||||
name="SensorParameterData",
|
||||
fields={
|
||||
"id": drf_serializers.IntegerField(),
|
||||
"code": drf_serializers.CharField(),
|
||||
"name_fa": drf_serializers.CharField(),
|
||||
"unit": drf_serializers.CharField(),
|
||||
"created_at": drf_serializers.DateTimeField(),
|
||||
"action": drf_serializers.CharField(),
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
400: OpenApiResponse(description="داده نامعتبر"),
|
||||
},
|
||||
examples=[
|
||||
OpenApiExample(
|
||||
"نمونه درخواست",
|
||||
value={"code": "soil_moisture", "name_fa": "رطوبت خاک", "unit": "%"},
|
||||
request_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request):
|
||||
serializer = SensorParameterSerializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
|
||||
Reference in New Issue
Block a user