Files
Logic/Modules/Ai/docs/location_and_farm_data_apps_explained.md
2026-05-11 03:27:21 +03:30

17 KiB

توضیح location_data/apps.py و farm_data/apps.py

این فایل یک توضیح کوتاه ولی کاربردی از دو فایل تنظیمات اپ Django در پروژه می‌دهد:

  • location_data/apps.py
  • farm_data/apps.py

همچنین برای فهم بهتر، به فیلدهای مهم مدل‌های مرتبط هم اشاره می‌کند تا معلوم شود این دو app در عمل چه داده‌هایی را مدیریت می‌کنند.


1) فایل location_data/apps.py

این فایل AppConfig مربوط به اپ location_data را تعریف می‌کند.

کلاس اصلی:

class SoilDataConfig(AppConfig):

فیلدها و بخش‌ها

default_auto_field = "django.db.models.BigAutoField"

  • مشخص می‌کند اگر در مدل‌های این اپ برای primary key چیزی تعریف نشده باشد، Django به‌صورت پیش‌فرض از BigAutoField استفاده کند.
  • BigAutoField یک شناسه عددی auto-increment بزرگ است.
  • این گزینه بیشتر برای مدل‌هایی مفید است که قرار است رکوردهای زیادی داشته باشند.

name = "location_data"

  • نام کامل اپ Django است.
  • Django با این مقدار اپ را register می‌کند.
  • این مقدار باید با مسیر ماژول اپ یکی باشد.

verbose_name = "Soil Data (SoilGrids)"

  • نام نمایشی اپ در Django admin یا جاهایی است که Django نام انسانی اپ را نشان می‌دهد.
  • این مقدار بیشتر جنبه نمایشی دارد و روی منطق برنامه اثر مستقیم ندارد.

propertyها و سرویس‌ها در location_data/apps.py

این فایل فقط metadata اپ را نگه نمی‌دارد؛ دو سرویس reusable هم از طریق AppConfig در اختیار بقیه پروژه می‌گذارد.

@cached_property def ndvi_health_service(self)

  • این property یک نمونه از NdviHealthService می‌سازد.
  • import آن از فایل .ndvi انجام می‌شود.
  • به دلیل cached_property فقط یک بار ساخته می‌شود و بعد همان instance دوباره استفاده می‌شود.

کاربرد:

  • برای تحلیل یا سرویس‌های مرتبط با NDVI
  • جلوگیری از ساخت مکرر object

@cached_property def soil_data_adapter(self)

این property adapter مناسب برای داده خاک را بر اساس تنظیمات پروژه انتخاب می‌کند.

دو adapter پشتیبانی می‌شوند:

  • SoilGridsAdapter
  • MockSoilDataAdapter

منطق انتخاب provider

مقدار provider از این setting خوانده می‌شود:

settings.SOIL_DATA_PROVIDER

اگر وجود نداشته باشد، مقدار پیش‌فرض:

"mock"

حالت اول: provider == "soilgrids"

در این حالت:

  • از SoilGridsAdapter استفاده می‌شود
  • timeout آن از این setting می‌آید:
settings.SOILGRIDS_TIMEOUT_SECONDS

اگر این setting هم نباشد، مقدار پیش‌فرض:

60

یعنی درخواست به provider واقعی SoilGrids حداکثر 60 ثانیه صبر می‌کند.

حالت دوم: provider == "mock"

در این حالت:

  • از MockSoilDataAdapter استفاده می‌شود
  • delay آن از این setting می‌آید:
settings.SOIL_MOCK_DELAY_SECONDS

اگر این setting هم نباشد، مقدار پیش‌فرض:

0.8

یعنی adapter تستی/نمایشی با تاخیر مصنوعی 0.8 ثانیه کار می‌کند.

حالت نامعتبر

اگر SOIL_DATA_PROVIDER چیزی غیر از soilgrids یا mock باشد:

  • ValueError رخ می‌دهد
  • یعنی config پروژه اشتباه است و provider شناخته نشده

ارتباط location_data/apps.py با فیلدهای واقعی داده

این فایل خودش مدل تعریف نمی‌کند، اما به‌صورت مستقیم برای کار با مدل‌های اپ location_data استفاده می‌شود؛ مهم‌ترین آن‌ها این‌ها هستند:

  • location_data.models.SoilLocation
  • location_data.models.SoilDepthData
  • location_data.models.NdviObservation

فیلدهای مهم SoilLocation

latitude

  • عرض جغرافیایی مرکز زمین
  • نوع آن DecimalField است
  • روی آن index وجود دارد
  • این نقطه معمولاً مرکز هندسی مزرعه است، نه لزوماً یکی از گوشه‌های مرز

longitude

  • طول جغرافیایی مرکز زمین
  • مثل latitude برای lookup و resolve کردن داده‌های خاک استفاده می‌شود

task_id

  • شناسه تسک Celery برای پردازش‌های async
  • وقتی fetch داده خاک یا پردازش مرتبط در صف باشد، می‌توان با این فیلد وضعیت را track کرد

farm_boundary

  • مرز مزرعه را به‌صورت JSON نگه می‌دارد
  • معمولاً به‌شکل Polygon یا ساختار corner-based ذخیره می‌شود
  • این فیلد خیلی مهم است چون فقط یک نقطه center نگه نمی‌دارید، بلکه شکل کلی زمین هم ثبت می‌شود

created_at / updated_at

  • زمان ایجاد و آخرین به‌روزرسانی رکورد

propertyهای مهم SoilLocation

center_latitude

  • فقط alias برای latitude است

center_longitude

  • فقط alias برای longitude است

is_complete

  • بررسی می‌کند آیا هر سه لایه خاک برای این location ثبت شده‌اند یا نه
  • شرط آن این است که تعداد depths دقیقاً 3 باشد

فیلدهای مهم SoilDepthData

این مدل برای هر location سه رکورد عمق خاک نگه می‌دارد:

  • 0-5cm
  • 5-15cm
  • 15-30cm

فیلدهای اصلی:

  • soil_location: ارتباط به SoilLocation
  • depth_label: مشخص می‌کند داده برای کدام عمق است
  • bdod: چگالی ظاهری خاک
  • cec: ظرفیت تبادل کاتیونی
  • cfvo: حجم قطعات درشت خاک
  • clay: درصد رس
  • nitrogen: مقدار نیتروژن
  • ocd و ocs: شاخص‌های کربن آلی
  • phh2o: pH خاک
  • sand: درصد شن
  • silt: درصد سیلت
  • soc: کربن آلی خاک
  • wv0010: رطوبت حجمی در فشار 10 kPa
  • wv0033: رطوبت در حدود ظرفیت زراعی
  • wv1500: رطوبت در نقطه پژمردگی دائم

این فیلدها برای شبیه‌سازی، آبیاری، و تخمین وضعیت واقعی خاک مهم هستند.

فیلدهای مهم NdviObservation

  • location: ارتباط با SoilLocation
  • observation_date: تاریخ مشاهده
  • mean_ndvi: میانگین NDVI
  • ndvi_map: داده مکانی NDVI
  • vegetation_health_class: کلاس سلامت پوشش گیاهی
  • satellite_source: منبع تصویر مثل sentinel-2
  • cloud_cover: درصد پوشش ابر
  • metadata: داده تکمیلی

نکته مهم: grid بندی زمین انجام می‌شود

بله، در لایه داده و سنجش از دور، مفهوم grid بندی وجود دارد.

اما این grid بندی در پروژه بیشتر در این دو سطح دیده می‌شود:

1) grid در NDVI map

در location_data/remote_sensing.py داده NDVI به‌صورت grid محاسبه و ذخیره می‌شود.

یعنی:

  • تصویر ماهواره‌ای به خانه‌های کوچک‌تر تقسیم می‌شود
  • برای هر خانه مقدار NDVI محاسبه می‌شود
  • خروجی در ndvi_map معمولاً به‌شکل grid نگه‌داری می‌شود

این یعنی وضعیت سلامت گیاه فقط به‌صورت یک عدد کلی نیست، بلکه می‌تواند روی بخش‌های مختلف زمین map شود.

2) grid/cell در adapter خاک

در location_data/soil_adapters.py هم منطق cell/grid دیده می‌شود، مخصوصاً در adapterهای mock یا interpolation-based.

یعنی:

  • مختصات lat/lon به cellهای شبکه‌ای نگاشت می‌شود
  • در بعضی محاسبات از grid_x و grid_y استفاده می‌شود
  • این کمک می‌کند داده خاک برای ناحیه‌های نزدیک، رفتار مکانی منطقی‌تری داشته باشد

نتیجه مهم

خود مدل SoilLocation یک مرکز زمین را نگه می‌دارد، ولی مرز مزرعه و NDVI grid باعث می‌شوند سیستم فقط point-based نباشد.

یعنی:

  • مرکز زمین برای lookup سریع و اتصال به داده خاک/هوا استفاده می‌شود
  • مرز مزرعه برای شکل واقعی زمین ذخیره می‌شود
  • grid بندی برای تحلیل مکانی، مخصوصاً در NDVI، انجام می‌شود

مرکز زمین چطور از مرز مزرعه به‌دست می‌آید

در farm_data/services.py از روی farm_boundary، مرکز هندسی polygon محاسبه می‌شود.

پس flow کلی این‌طور است:

  1. مرز مزرعه ارسال می‌شود
  2. polygon نرمال می‌شود
  3. centroid هندسی آن محاسبه می‌شود
  4. یک SoilLocation برای center ساخته یا پیدا می‌شود
  5. بعد داده خاک، NDVI و هوا به این location متصل می‌شوند

پس زمین فقط با یک نقطه خام ثبت نمی‌شود؛ اول مرز دارد، بعد center از روی آن به‌دست می‌آید.


متدهای کمکی location_data/apps.py

get_ndvi_health_service()

  • خروجی self.ndvi_health_service را برمی‌گرداند
  • یک accessor ساده برای گرفتن سرویس NDVI است

get_soil_data_adapter()

  • خروجی self.soil_data_adapter را برمی‌گرداند
  • بقیه بخش‌های پروژه از این متد برای گرفتن adapter فعال استفاده می‌کنند /

فیلدها و settingهای مهم مرتبط با location_data/apps.py

فیلدهای AppConfig

  • default_auto_field: نوع primary key پیش‌فرض مدل‌ها
  • name: نام داخلی اپ
  • verbose_name: نام نمایشی اپ

settingهای استفاده‌شده

  • SOIL_DATA_PROVIDER: انتخاب provider فعال خاک
  • SOILGRIDS_TIMEOUT_SECONDS: timeout برای provider واقعی SoilGrids
  • SOIL_MOCK_DELAY_SECONDS: تاخیر مصنوعی برای provider mock

2) فایل farm_data/apps.py

این فایل AppConfig مربوط به اپ farm_data را تعریف می‌کند.

کلاس اصلی:

class FarmDataConfig(AppConfig):

فیلدها

default_auto_field = "django.db.models.BigAutoField"

  • مثل اپ قبلی، تعیین می‌کند primary key پیش‌فرض مدل‌های این اپ از نوع BigAutoField باشد.

name = "farm_data"

  • نام داخلی و ماژول اپ Django است.
  • برای شناسایی اپ در INSTALLED_APPS و registry داخلی Django استفاده می‌شود.

label = "sensor_data"

  • label داخلی اپ در registry Django است.
  • این فیلد زمانی مهم می‌شود که:
    • بخواهید نام registry اپ با name فرق داشته باشد
    • یا از تداخل نام اپ‌ها جلوگیری کنید
  • در این پروژه، اپ farm_data با label داخلی sensor_data شناخته می‌شود.

نکته:

  • label باید در کل پروژه یکتا باشد.
  • این مقدار ممکن است در migrationها، relationها یا lookupهای app registry اثر داشته باشد.

verbose_name = "farm-data"

  • نام نمایشی اپ است.
  • بیشتر برای admin و نمایش انسانی استفاده می‌شود.

نکته مهم درباره farm_data/apps.py

برخلاف location_data/apps.py، این فایل:

  • cached_property ندارد
  • service locator ندارد
  • adapter یا provider انتخاب نمی‌کند

یعنی فعلاً فقط نقش config پایه اپ را دارد.


ارتباط farm_data/apps.py با فیلدهای واقعی داده

این app بیشتر داده‌های farm-level و sensor-level را نگه می‌دارد. مهم‌ترین مدل‌هایش:

  • farm_data.models.SensorData
  • farm_data.models.SensorParameter
  • farm_data.models.ParameterUpdateLog

فیلدهای مهم SensorData

farm_uuid

  • شناسه یکتای مزرعه
  • primary key این مدل است
  • هر رکورد SensorData نماینده یک مزرعه است

center_location

  • ارتباط به location_data.SoilLocation
  • یعنی این مزرعه به یک location مرکزی وصل است
  • از همین نقطه مرکزی برای weather/soil/simulation استفاده می‌شود

weather_forecast

  • ارتباط اختیاری با weather.WeatherForecast
  • اگر موجود باشد، forecast منتخب یا آخرین forecast به مزرعه وصل می‌شود

sensor_payload

  • مهم‌ترین فیلد این مدل است
  • داده سنسورها به‌صورت JSON نگه‌داری می‌شود
  • ساختار معمول آن شبیه این است:
{
  "sensor-7-1": {
    "soil_moisture": 25.5,
    "soil_temperature": 22.3,
    "soil_ph": 7.2
  }
}

مزیت این ساختار:

  • چند سنسور در یک مزرعه پشتیبانی می‌شود
  • هر سنسور می‌تواند فیلدهای خاص خودش را داشته باشد
  • schema سنسورها rigid نیست

plants

  • رابطه چندبه‌چند با plant.Plant
  • یعنی یک farm می‌تواند چند گیاه مرتبط داشته باشد

irrigation_method

  • روش آبیاری انتخاب‌شده برای مزرعه
  • برای recommendation و planning مهم است

created_at / updated_at

  • زمان ایجاد و آخرین ویرایش رکورد

propertyهای مهم SensorPayloadMixin

مدل SensorData از SensorPayloadMixin ارث می‌گیرد و این helperها را دارد:

_payload()

  • payload را فقط وقتی dict معتبر باشد برمی‌گرداند

get_sensor_block(sensor_key=None)

  • اگر sensor_key بدهید، همان بلوک سنسور را برمی‌گرداند
  • اگر ندهید، اولین بلوک معتبر را برمی‌گرداند

get_metric(metric_name, sensor_key=None)

  • یک metric خاص را از payload پیدا می‌کند
  • اول در sensor مشخص‌شده می‌گردد
  • اگر پیدا نشد، در بقیه blockها جستجو می‌کند

propertyهای آماده

این propertyها shortcut هستند:

  • soil_moisture
  • soil_temperature
  • soil_ph
  • electrical_conductivity
  • nitrogen
  • phosphorus
  • potassium

یعنی به‌جای parse دستی JSON، مستقیم می‌توان این متریک‌ها را خواند.

فیلدهای مهم SensorParameter

این مدل dictionary پارامترهای سنسور را نگه می‌دارد.

sensor_key

  • کلید سنسور مثل sensor-7-1

code

  • کد پارامتر مثل soil_moisture

name_fa

  • نام فارسی پارامتر

unit

  • واحد پارامتر مثل % یا dS/m

data_type

  • نوع داده مثل float, int, string, bool

metadata

  • داده تکمیلی برای UI یا validation
  • مثلاً:
    • بازه مجاز
    • توضیح
    • تنظیمات نمایش

فیلدهای مهم ParameterUpdateLog

  • parameter: ارتباط به SensorParameter
  • action: نوع عملیات مثل added یا modified
  • payload: خلاصه تغییرات
  • updated_at: زمان ثبت لاگ

این مدل برای audit و پیگیری تغییرات پارامترها مفید است.


جمع‌بندی

location_data/apps.py

  • هم metadata اپ را نگه می‌دارد
  • هم سرویس و adapter در اختیار پروژه می‌گذارد
  • هم از settingها برای انتخاب provider واقعی یا mock استفاده می‌کند
  • و در عمل با location center، مرز مزرعه، داده لایه‌های خاک و gridهای NDVI کار می‌کند

farm_data/apps.py

  • فقط config پایه AppConfig را تعریف می‌کند
  • نقش آن بیشتر register کردن اپ با نام و label مشخص است
  • اما داده‌های اصلی مزرعه مثل farm_uuid، sensor_payload، گیاه، روش آبیاری و اتصال به center location در مدل‌های همین app نگه‌داری می‌شوند