513 lines
17 KiB
Markdown
513 lines
17 KiB
Markdown
|
|
# توضیح `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` را تعریف میکند.
|
||
|
|
|
||
|
|
کلاس اصلی:
|
||
|
|
|
||
|
|
```python
|
||
|
|
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 خوانده میشود:
|
||
|
|
|
||
|
|
```python
|
||
|
|
settings.SOIL_DATA_PROVIDER
|
||
|
|
```
|
||
|
|
|
||
|
|
اگر وجود نداشته باشد، مقدار پیشفرض:
|
||
|
|
|
||
|
|
```python
|
||
|
|
"mock"
|
||
|
|
```
|
||
|
|
|
||
|
|
#### حالت اول: `provider == "soilgrids"`
|
||
|
|
|
||
|
|
در این حالت:
|
||
|
|
|
||
|
|
- از `SoilGridsAdapter` استفاده میشود
|
||
|
|
- timeout آن از این setting میآید:
|
||
|
|
|
||
|
|
```python
|
||
|
|
settings.SOILGRIDS_TIMEOUT_SECONDS
|
||
|
|
```
|
||
|
|
|
||
|
|
اگر این setting هم نباشد، مقدار پیشفرض:
|
||
|
|
|
||
|
|
```python
|
||
|
|
60
|
||
|
|
```
|
||
|
|
|
||
|
|
یعنی درخواست به provider واقعی SoilGrids حداکثر 60 ثانیه صبر میکند.
|
||
|
|
|
||
|
|
#### حالت دوم: `provider == "mock"`
|
||
|
|
|
||
|
|
در این حالت:
|
||
|
|
|
||
|
|
- از `MockSoilDataAdapter` استفاده میشود
|
||
|
|
- delay آن از این setting میآید:
|
||
|
|
|
||
|
|
```python
|
||
|
|
settings.SOIL_MOCK_DELAY_SECONDS
|
||
|
|
```
|
||
|
|
|
||
|
|
اگر این setting هم نباشد، مقدار پیشفرض:
|
||
|
|
|
||
|
|
```python
|
||
|
|
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` را تعریف میکند.
|
||
|
|
|
||
|
|
کلاس اصلی:
|
||
|
|
|
||
|
|
```python
|
||
|
|
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 نگهداری میشود
|
||
|
|
- ساختار معمول آن شبیه این است:
|
||
|
|
|
||
|
|
```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 نگهداری میشوند
|