Files
Backend/sensor_catalog/SensorCatalogListView.md
T
2026-04-29 01:27:16 +03:30

8.9 KiB

مستند API کاتالوگ سنسورها

این فایل API ثبت‌شده در sensor_catalog/urls.py را به‌صورت کامل توضیح می‌دهد.

فایل route

فایل route این app:

sensor_catalog/urls.py

محتوای آن:

from django.urls import path

from .views import SensorCatalogListView

urlpatterns = [
    path("", SensorCatalogListView.as_view(), name="sensor-catalog-list"),
]

آدرس نهایی endpoint

این route در config/urls.py این‌طور mount شده است:

path("api/sensor-catalog/", include("sensor_catalog.urls"))

پس آدرس نهایی API این است:

GET /api/sensor-catalog/

هدف API

این endpoint برای گرفتن لیست کاتالوگ سنسورها استفاده می‌شود.

منظور از کاتالوگ سنسور، تعریف مرجع هر نوع سنسور است؛ مثلا:

  • کد سنسور
  • نام سنسور
  • توضیحات
  • فیلدهای خروجی سنسور
  • نمونه payload
  • منبع تغذیه‌های پشتیبانی‌شده

این API بیشتر برای frontend یا تنظیمات سیستم مفید است تا بداند چه نوع سنسورهایی در سیستم تعریف شده‌اند و هر سنسور چه ساختاری دارد.

View مربوطه

این endpoint در فایل sensor_catalog/views.py پیاده‌سازی شده است:

class SensorCatalogListView(APIView):
    permission_classes = [IsAuthenticated]

این یعنی:

  • فقط متد GET پشتیبانی می‌شود
  • کاربر باید authenticated باشد

احراز هویت و دسترسی

این View از:

permission_classes = [IsAuthenticated]

استفاده می‌کند.

در این پروژه به‌صورت پیش‌فرض authentication از طریق JWT انجام می‌شود، چون در config/settings.py مقدار زیر تعریف شده:

"DEFAULT_AUTHENTICATION_CLASSES": [
    "rest_framework_simplejwt.authentication.JWTAuthentication",
]

پس اگر کاربر توکن معتبر نداشته باشد، این API پاسخ 401 Unauthorized برمی‌گرداند.

رفتار endpoint

در متد get این View:

def get(self, request):
    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)

این منطق اجرا می‌شود:

  1. همه رکوردهای SensorCatalog از دیتابیس خوانده می‌شوند
  2. خروجی بر اساس code مرتب می‌شود
  3. داده‌ها با serializer به JSON تبدیل می‌شوند
  4. پاسخ استاندارد با code و msg و data برگردانده می‌شود

مدل دیتابیس

مدل این API در sensor_catalog/models.py قرار دارد:

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)
    supported_power_sources = models.JSONField(default=list, blank=True)
    returned_data_fields = models.JSONField(default=list, blank=True)
    sample_payload = models.JSONField(default=dict, blank=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

معنی فیلدها

  • uuid: شناسه یکتا برای هر کاتالوگ
  • code: کد یکتا و فنی سنسور
  • name: نام قابل نمایش سنسور
  • description: توضیح سنسور
  • customizable_fields: فیلدهایی که موقع ساخت/پیکربندی سنسور ممکن است قابل تنظیم باشند
  • supported_power_sources: نوع منبع تغذیه‌های پشتیبانی‌شده
  • returned_data_fields: فیلدهایی که این سنسور در payload خود برمی‌گرداند
  • sample_payload: یک نمونه payload برای درک ساختار داده
  • is_active: فعال یا غیرفعال بودن این کاتالوگ
  • created_at و updated_at: زمان ایجاد و آخرین بروزرسانی

Serializer خروجی

serializer این endpoint در sensor_catalog/serializers.py تعریف شده است:

class SensorCatalogSerializer(serializers.ModelSerializer):
    class Meta:
        model = SensorCatalog
        fields = [
            "uuid",
            "code",
            "name",
            "description",
            "customizable_fields",
            "supported_power_sources",
            "returned_data_fields",
            "sample_payload",
            "is_active",
        ]
        read_only_fields = fields

نکته مهم

این serializer فقط این فیلدها را در خروجی برمی‌گرداند:

  • uuid
  • code
  • name
  • description
  • customizable_fields
  • supported_power_sources
  • returned_data_fields
  • sample_payload
  • is_active

پس فیلدهای created_at و updated_at در پاسخ این API نیستند.

ورودی API

این endpoint ورودی body یا query param خاصی ندارد.

فقط کافی است کاربر authenticated باشد.

نمونه درخواست

GET /api/sensor-catalog/
Authorization: Bearer <access_token>

خروجی موفق

نمونه پاسخ موفق:

{
  "code": 200,
  "msg": "success",
  "data": [
    {
      "uuid": "11111111-1111-1111-1111-111111111111",
      "code": "sensor_7_soil_moisture_sensor_v1_2",
      "name": "Sensor 7 - Soil Moisture Sensor v1.2",
      "description": "Measures only soil moisture using electrical resistance between two metal probes.",
      "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
    },
    {
      "uuid": "22222222-2222-2222-2222-222222222222",
      "code": "legacy_sensor",
      "name": "Legacy Sensor",
      "description": "",
      "customizable_fields": [],
      "supported_power_sources": ["direct_power"],
      "returned_data_fields": ["status"],
      "sample_payload": {
        "status": "offline"
      },
      "is_active": false
    }
  ]
}

ترتیب خروجی

خروجی با این دستور مرتب می‌شود:

SensorCatalog.objects.order_by("code")

یعنی لیست همیشه بر اساس code به صورت صعودی برگردانده می‌شود.

سناریوهای کاربردی

این API معمولا برای این موارد استفاده می‌شود:

  • ساخت dropdown برای انتخاب نوع سنسور
  • نمایش ساختار داده قابل انتظار از یک سنسور
  • فهمیدن اینکه هر سنسور چه فیلدهایی برمی‌گرداند
  • ساخت فرم‌های داینامیک برای پیکربندی سنسور
  • نمایش sample_payload در Swagger یا UI مدیریتی

وضعیت‌های خطا

401 Unauthorized

اگر کاربر login نباشد یا توکن معتبر نداشته باشد.

200 با لیست خالی

اگر هیچ رکوردی در جدول sensor_catalogs وجود نداشته باشد، پاسخ موفق است اما data خالی خواهد بود:

{
  "code": 200,
  "msg": "success",
  "data": []
}

تست موجود

برای این endpoint تست در فایل sensor_catalog/tests.py وجود دارد.

تست اصلی بررسی می‌کند که:

  • کاربر authenticated بتواند endpoint را صدا بزند
  • پاسخ 200 باشد
  • همه سنسورهای موجود برگردانده شوند

نمونه assertion:

self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["code"], 200)
self.assertEqual(len(response.data["data"]), 2)

خلاصه

API موجود در sensor_catalog/urls.py فقط یک endpoint دارد:

  • GET /api/sensor-catalog/

این endpoint:

  • نیاز به احراز هویت دارد
  • همه کاتالوگ‌های سنسور را از دیتابیس می‌خواند
  • آن‌ها را بر اساس code مرتب می‌کند
  • اطلاعات ساختاری سنسورها را برای frontend یا پنل مدیریتی برمی‌گرداند

فایل‌های مرتبط

  • sensor_catalog/urls.py
  • sensor_catalog/views.py
  • sensor_catalog/serializers.py
  • sensor_catalog/models.py
  • sensor_catalog/tests.py
  • config/urls.py