Files
Backend/docs/location_data_api_responses_fa.md
T

1032 lines
23 KiB
Markdown
Raw Normal View History

2026-05-13 22:29:18 +03:30
# مستند کامل response های Location Data
این فایل، response همه endpointهای اصلی `Location Data` را به زبان ساده و دقیق توضیح می‌دهد.
مسیرهای این مستند:
- `GET /api/location-data/`
- `POST /api/location-data/`
- `POST /api/location-data/ndvi-health/`
- `GET /api/location-data/remote-sensing/`
- `POST /api/location-data/remote-sensing/`
- `GET /api/location-data/remote-sensing/cluster-blocks/{cluster_uuid}/live/`
- `GET /api/location-data/remote-sensing/cluster-recommendations/`
- `GET /api/location-data/remote-sensing/results/{result_id}/k-options/`
- `POST /api/location-data/remote-sensing/results/{result_id}/k-options/activate/`
- `GET /api/location-data/remote-sensing/runs/{run_id}/status/`
## 1) ساختار عمومی همه response ها
تقریبا همه endpointها این envelope را دارند:
```json
{
"code": 200,
"msg": "success",
"data": {}
}
```
توضیح فیلدها:
- `code`: کد منطقی response در body
- `msg`: پیام کوتاه
- `data`: payload اصلی
در خطاها معمولا یکی از این دو حالت برمی‌گردد:
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"field_name": ["error message"]
}
}
```
یا:
```json
{
"code": 404,
"msg": "location پیدا نشد.",
"data": null
}
```
## 2) `GET /api/location-data/`
کاربرد:
- خواندن ساختار ذخیره‌شده مزرعه
- خواندن بلوک‌ها
- خواندن subdivisionها
- خواندن snapshotهای ماهواره‌ای ذخیره/تجمیع‌شده
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"source": "database",
"id": 12,
"lon": "51.389000",
"lat": "35.689200",
"input_block_count": 2,
"farm_boundary": {},
"block_layout": {},
"block_subdivisions": [],
"satellite_snapshots": []
}
}
```
### توضیح فیلدهای `data`
- `source`: در این endpoint همیشه از دیتابیس است و معمولا مقدار آن `database` است
- `id`: شناسه داخلی `SoilLocation`
- `lon`: طول جغرافیایی location
- `lat`: عرض جغرافیایی location
- `input_block_count`: تعداد بلوک‌های تعریف‌شده برای این مزرعه
- `farm_boundary`: مرز کل مزرعه به صورت GeoJSON
- `block_layout`: ساختار کلی بلوک‌ها، وضعیت الگوریتم، sub-blockها و metadata سطح مزرعه
- `block_subdivisions`: لیست subdivisionهای سطح بلوک
- `satellite_snapshots`: خلاصه‌های سنجش‌ازدور هر بلوک و هر sub-block
### ساختار هر آیتم `block_subdivisions`
```json
{
"block_code": "block-1",
"chunk_size_sqm": 900,
"grid_points": [],
"centroid_points": [],
"grid_point_count": 0,
"centroid_count": 0,
"elbow_plot": null,
"status": "defined",
"metadata": {},
"created_at": "2026-05-13T14:00:00Z",
"updated_at": "2026-05-13T14:00:00Z"
}
```
توضیح:
- `block_code`: کد بلوک
- `chunk_size_sqm`: اندازه هر سلول تحلیل
- `grid_points`: نقاط grid تولیدشده
- `centroid_points`: centroidهای grid
- `grid_point_count`: تعداد نقاط grid
- `centroid_count`: تعداد centroidها
- `elbow_plot`: تصویر elbow plot اگر ساخته شده باشد
- `status`: وضعیت subdivision مثل `defined`، `created`، `subdivided`
- `metadata`: داده‌های تکمیلی
### `400`
وقتی `lat` یا `lon` نامعتبر باشد:
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"lat": ["..."],
"lon": ["..."]
}
}
```
### `404`
وقتی location پیدا نشود:
```json
{
"code": 404,
"msg": "location پیدا نشد.",
"data": null
}
```
## 3) `POST /api/location-data/`
کاربرد:
- ثبت یا به‌روزرسانی مزرعه
- ثبت مرز مزرعه
- ثبت بلوک‌های کشاورز
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"source": "created",
"id": 12,
"lon": "51.389000",
"lat": "35.689200",
"input_block_count": 2,
"farm_boundary": {},
"block_layout": {},
"block_subdivisions": [],
"satellite_snapshots": []
}
}
```
### توضیح `source`
- `created`: این location تازه ساخته شده
- `database`: location از قبل وجود داشته و فقط update شده یا همان داده قبلی برگشته
### `400`
حالت اول: body نامعتبر باشد:
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"farm_boundary": ["مختصات گوشه‌های کل زمین باید ارسال شود."]
}
}
```
حالت دوم: مرز کل مزرعه نه در request آمده و نه قبلا ذخیره شده:
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"farm_boundary": [
"برای ثبت location باید گوشه‌های کل زمین ارسال یا قبلاً ذخیره شده باشد."
]
}
}
```
## 4) `POST /api/location-data/ndvi-health/`
کاربرد:
- برگرداندن وضعیت سلامت پوشش گیاهی مزرعه بر اساس NDVI
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"ndviIndex": 0.63,
"mean_ndvi": 0.63,
"ndvi_map": {},
"vegetation_health_class": "healthy",
"observation_date": "2026-05-12",
"satellite_source": "sentinel-2",
"healthData": [
{
"title": "میانگین NDVI",
"value": 0.63,
"color": "green",
"icon": "leaf"
}
]
}
}
```
### توضیح فیلدها
- `ndviIndex`: شاخص اصلی NDVI برای UI
- `mean_ndvi`: میانگین NDVI محاسبه‌شده
- `ndvi_map`: داده نقشه یا لایه NDVI
- `vegetation_health_class`: کلاس سلامت پوشش گیاهی
- `observation_date`: تاریخ مشاهده
- `satellite_source`: منبع داده ماهواره‌ای
- `healthData`: کارت‌های خلاصه برای نمایش در فرانت
### ساختار هر آیتم `healthData`
- `title`: عنوان آیتم
- `value`: مقدار عددی یا ساختار JSON
- `color`: رنگ پیشنهادی UI
- `icon`: آیکون پیشنهادی UI
### `400`
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"farm_uuid": ["..."]
}
}
```
### `404`
```json
{
"code": 404,
"msg": "مزرعه پیدا نشد.",
"data": null
}
```
## 5) `GET /api/location-data/remote-sensing/`
کاربرد:
- فقط نتایج cache شده remote sensing و subdivision را می‌خواند
- هیچ پردازش جدیدی اجرا نمی‌کند
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"status": "success",
"source": "database",
"location": {},
"block_code": "",
"chunk_size_sqm": 900,
"temporal_extent": {
"start_date": "2026-04-12",
"end_date": "2026-05-12"
},
"summary": {
"cell_count": 12,
"ndvi_mean": 0.54,
"ndwi_mean": 0.21,
"soil_vv_db_mean": -8.92
},
"cells": [],
"run": {},
"subdivision_result": {},
"pagination": {},
"metadata": {
"farm_uuid": "11111111-1111-1111-1111-111111111111",
"cache_hit": true
}
}
}
```
### حالت‌های مهم `status`
- `success`: داده کامل در DB موجود است
- `processing`: run در حال انجام است و هنوز observation نهایی کامل نشده
- `not_found`: runی وجود داشته ولی observation قابل استفاده برنگشته
### توضیح فیلدها
- `status`: وضعیت نتیجه
- `source`: معمولا `database` یا `processing`
- `location`: همان ساختار `SoilLocationResponse`
- `block_code`: برای full farm معمولا رشته خالی `""`
- `chunk_size_sqm`: اندازه سلول تحلیل
- `temporal_extent.start_date`: شروع بازه تحلیل
- `temporal_extent.end_date`: پایان بازه تحلیل
- `summary`: خلاصه آماری observationها
- `cells`: observationهای صفحه فعلی
- `run`: اطلاعات run مرتبط
- `subdivision_result`: نتیجه clustering و KMeans
- `pagination`: اطلاعات صفحه‌بندی `cells` و گاهی `assignments`
- `metadata.cache_hit`: نشان می‌دهد پاسخ از cache/DB آمده
### ساختار `summary`
- `cell_count`: تعداد سلول‌ها
- `ndvi_mean`: میانگین NDVI
- `ndwi_mean`: میانگین NDWI
- `soil_vv_db_mean`: میانگین `soil_vv_db`
### ساختار هر آیتم `cells`
```json
{
"cell_code": "cell-1",
"block_code": "",
"chunk_size_sqm": 900,
"centroid_lat": "35.689500",
"centroid_lon": "51.389500",
"geometry": {},
"temporal_start": "2026-04-12",
"temporal_end": "2026-05-12",
"ndvi": 0.61,
"ndwi": 0.22,
"soil_vv": 0.13,
"soil_vv_db": -8.860566,
"metadata": {}
}
```
### ساختار `run`
```json
{
"id": 10,
"block_code": "",
"chunk_size_sqm": 900,
"temporal_start": "2026-04-12",
"temporal_end": "2026-05-12",
"status": "success",
"status_label": "completed",
"pipeline_status": "completed",
"stage": "completed",
"selected_features": ["ndvi", "ndwi", "soil_vv_db"],
"requested_cluster_count": null,
"metadata": {},
"error_message": "",
"started_at": null,
"finished_at": null,
"created_at": "2026-05-13T14:00:00Z",
"updated_at": "2026-05-13T14:00:00Z"
}
```
### ساختار `subdivision_result`
```json
{
"id": 5,
"block_code": "",
"chunk_size_sqm": 900,
"temporal_start": "2026-04-12",
"temporal_end": "2026-05-12",
"cluster_count": 3,
"selected_features": ["ndvi", "ndwi", "soil_vv_db"],
"skipped_cell_codes": [],
"metadata": {},
"available_k_options": [],
"cluster_blocks": [],
"assignments": [],
"created_at": "2026-05-13T14:00:00Z",
"updated_at": "2026-05-13T14:00:00Z"
}
```
### ساختار هر `assignment`
```json
{
"cell_code": "cell-1",
"cluster_label": 0,
"centroid_lat": "35.689500",
"centroid_lon": "51.389500",
"raw_feature_values": {
"ndvi": 0.61
},
"scaled_feature_values": {
"ndvi": 0.21
}
}
```
### ساختار هر `cluster_block`
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"sub_block_code": "cluster-0",
"cluster_label": 0,
"chunk_size_sqm": 900,
"centroid_lat": "35.689500",
"centroid_lon": "51.389500",
"center_cell_code": "cell-1",
"center_cell_lat": "35.689500",
"center_cell_lon": "51.389500",
"cell_count": 4,
"cell_codes": ["cell-1", "cell-2"],
"geometry": {},
"metadata": {},
"created_at": "2026-05-13T14:00:00Z",
"updated_at": "2026-05-13T14:00:00Z"
}
```
### `400`
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"farm_uuid": ["..."]
}
}
```
### `404`
```json
{
"code": 404,
"msg": "location پیدا نشد.",
"data": null
}
```
## 6) `POST /api/location-data/remote-sensing/`
کاربرد:
- اجرای async تحلیل سنجش‌ازدور
- ساخت run و task قابل polling
- اگر داده قبلا در DB موجود باشد هم یک `task_id` tracking برمی‌گرداند تا status بلافاصله نتیجه را بدهد
### response موفق `202`
```json
{
"code": 202,
"msg": "تحلیل سنجش‌ازدور در صف قرار گرفت.",
"data": {
"status": "processing",
"source": "processing",
"location": {},
"block_code": "",
"chunk_size_sqm": 900,
"temporal_extent": {
"start_date": "2026-04-12",
"end_date": "2026-05-12"
},
"summary": {
"cell_count": 0,
"ndvi_mean": null,
"ndwi_mean": null,
"soil_vv_db_mean": null
},
"cells": [],
"run": {},
"task_id": "11111111-1111-1111-1111-111111111111"
}
}
```
### دو حالت مهم
#### حالت اول: واقعا task جدید ساخته شده
- `status = processing`
- `source = processing`
- `task_id` مربوط به Celery run جدید است
#### حالت دوم: data از قبل در DB وجود دارد
- باز هم `202` برمی‌گردد
- `status` ممکن است `success` باشد
- `source` معمولا `database` است
- `task_id` برای polling ساخته می‌شود
- `GET /runs/{run_id}/status/` بلافاصله نتیجه کامل را می‌دهد
### `400`
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"farm_uuid": ["..."]
}
}
```
### `404`
```json
{
"code": 404,
"msg": "location پیدا نشد.",
"data": null
}
```
## 7) `GET /api/location-data/remote-sensing/cluster-blocks/{cluster_uuid}/live/`
کاربرد:
- دریافت metricهای زنده یا cache شده برای یک cluster block
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"status": "success",
"source": "database",
"cluster_block": {},
"temporal_extent": {
"start_date": "2026-04-12",
"end_date": "2026-05-12"
},
"selected_features": ["ndvi", "ndwi", "soil_vv_db"],
"summary": {
"cell_count": 2,
"ndvi_mean": 0.54,
"ndwi_mean": 0.17,
"soil_vv_db_mean": -9.0
},
"metrics": {
"ndvi": 0.54,
"ndwi": 0.17,
"soil_vv": 0.14,
"soil_vv_db": -9.0
},
"metadata": {
"requested_cluster_uuid": "11111111-1111-1111-1111-111111111111",
"cache_hit": true
}
}
}
```
### توضیح فیلدها
- `source`: اگر از observationهای DB آمده باشد `database` و اگر مستقیم از openEO آمده باشد `openeo`
- `cluster_block`: ساختار کامل sub-block
- `selected_features`: metricهایی که برای تحلیل استفاده می‌شوند
- `summary`: خلاصه آماری cluster
- `metrics`: metric تجمیع‌شده همان cluster
- `metadata`: اطلاعات تکمیلی مثل backend، source_result_id، source_run_id
### `400`
- پارامترهای تاریخ نامعتبر باشند
- یا هندسه cluster معتبر نباشد
نمونه:
```json
{
"code": 400,
"msg": "هندسه زیر‌بلاک KMeans نامعتبر است.",
"data": {
"cluster_uuid": ["11111111-1111-1111-1111-111111111111"]
}
}
```
### `404`
```json
{
"code": 404,
"msg": "زیر‌بلاک KMeans پیدا نشد.",
"data": null
}
```
### `502`
وقتی openEO پاسخ ندهد:
```json
{
"code": 502,
"msg": "خواندن داده از openEO ناموفق بود.",
"data": {
"detail": "..."
}
}
```
## 8) `GET /api/location-data/remote-sensing/cluster-recommendations/`
کاربرد:
- مقایسه گیاه‌های ثبت‌شده در `farm_data`
- استفاده از داده کلاسترها
- استفاده از `crop_simulation`
- پیشنهاد بهترین گیاه برای هر cluster
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"farm_uuid": "11111111-1111-1111-1111-111111111111",
"location_id": 12,
"evaluated_plant_count": 2,
"cluster_count": 2,
"registered_plants": [],
"clusters": [],
"source_metadata": {}
}
}
```
### توضیح فیلدهای سطح بالا
- `farm_uuid`: شناسه مزرعه
- `location_id`: شناسه داخلی location
- `evaluated_plant_count`: تعداد گیاه‌هایی که وارد simulation شده‌اند
- `cluster_count`: تعداد clusterهای بررسی‌شده
- `registered_plants`: گیاه‌های ثبت‌شده روی مزرعه
- `clusters`: خروجی نهایی هر cluster
- `source_metadata`: metadata کلی پاسخ
### ساختار هر آیتم `registered_plants`
```json
{
"plant_id": 101,
"plant_name": "Tomato",
"position": 0,
"stage": "vegetative"
}
```
### ساختار هر آیتم `clusters`
```json
{
"block_code": "block-1",
"cluster_uuid": "11111111-1111-1111-1111-111111111111",
"sub_block_code": "cluster-0",
"cluster_label": 0,
"temporal_extent": {
"start_date": "2026-04-12",
"end_date": "2026-05-12"
},
"cluster_block": {},
"satellite_metrics": {
"ndvi": 0.51,
"ndwi": 0.24,
"soil_vv": 0.13
},
"sensor_metrics": {},
"resolved_metrics": {
"ndvi": 0.51,
"ndwi": 0.24,
"soil_vv": 0.13
},
"candidate_plants": [],
"suggested_plant": {},
"source_metadata": {}
}
```
### ساختار هر آیتم `candidate_plants`
```json
{
"plant_id": 101,
"plant_name": "Tomato",
"position": 0,
"stage": "vegetative",
"score": 150.0,
"predicted_yield": 150.0,
"predicted_yield_tons": 0.15,
"biomass": 300.0,
"max_lai": 4.2,
"simulation_engine": "pcse",
"simulation_model_name": "Wofost81_NWLP_CWB_CNB",
"simulation_warning": null,
"supporting_metrics": {}
}
```
### `400`
وقتی مزرعه گیاه ثبت‌شده نداشته باشد یا پیش‌نیاز simulation کامل نباشد:
```json
{
"code": 400,
"msg": "برای این مزرعه هنوز هیچ گیاهی در farm_data ثبت نشده است.",
"data": null
}
```
### `404`
وقتی مزرعه یا خروجی KMeans پیدا نشود:
```json
{
"code": 404,
"msg": "برای این مزرعه هنوز خروجی KMeans در location_data ثبت نشده است.",
"data": null
}
```
## 9) `GET /api/location-data/remote-sensing/results/{result_id}/k-options/`
کاربرد:
- لیست همه Kهای ذخیره‌شده برای یک subdivision result
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"result_id": 5,
"active_requested_k": 3,
"recommended_requested_k": 4,
"options": []
}
}
```
### توضیح فیلدها
- `result_id`: شناسه subdivision result
- `active_requested_k`: K فعال فعلی
- `recommended_requested_k`: K پیشنهادی سیستم
- `options`: لیست کامل گزینه‌ها
### ساختار هر آیتم `options`
```json
{
"id": 11,
"requested_k": 3,
"effective_cluster_count": 3,
"is_active": true,
"is_recommended": false,
"selection_source": "user",
"metadata": {},
"cluster_blocks": [],
"created_at": "2026-05-13T14:00:00Z",
"updated_at": "2026-05-13T14:00:00Z"
}
```
### ساختار هر `cluster_blocks` داخل option
```json
{
"cluster_label": 0,
"sub_block_code": "cluster-0",
"chunk_size_sqm": 900,
"centroid_lat": "35.689500",
"centroid_lon": "51.389500",
"center_cell_code": "cell-1",
"center_cell_lat": "35.689500",
"center_cell_lon": "51.389500",
"cell_count": 4,
"cell_codes": ["cell-1", "cell-2"],
"geometry": {},
"metadata": {}
}
```
### `404`
```json
{
"code": 404,
"msg": "subdivision result پیدا نشد.",
"data": null
}
```
## 10) `POST /api/location-data/remote-sensing/results/{result_id}/k-options/activate/`
کاربرد:
- فعال‌سازی یکی از Kهای ذخیره‌شده
### response موفق `200`
```json
{
"code": 200,
"msg": "success",
"data": {
"result_id": 5,
"activated_requested_k": 4,
"subdivision_result": {}
}
}
```
### توضیح فیلدها
- `result_id`: شناسه result
- `activated_requested_k`: K که الان active شده
- `subdivision_result`: خروجی کامل subdivision بعد از sync شدن روی K جدید
### `400`
حالت اول: body نامعتبر
```json
{
"code": 400,
"msg": "داده نامعتبر.",
"data": {
"requested_k": ["..."]
}
}
```
حالت دوم: K داخل optionها وجود ندارد
```json
{
"code": 400,
"msg": "K انتخابی برای این subdivision result موجود نیست.",
"data": {
"requested_k": [7]
}
}
```
### `404`
```json
{
"code": 404,
"msg": "subdivision result پیدا نشد.",
"data": null
}
```
## 11) `GET /api/location-data/remote-sensing/runs/{run_id}/status/`
کاربرد:
- polling وضعیت run
- دیدن stageهای pipeline
- اگر run کامل شده باشد، دیدن نتیجه نهایی
- اگر run از نوع cache-hit باشد، دیدن نتیجه کامل DB بلافاصله
### response موفق `200` در حالت pending/running
```json
{
"code": 200,
"msg": "success",
"data": {
"status": "running",
"source": "database",
"run": {},
"task_id": "11111111-1111-1111-1111-111111111111",
"task": {
"current_stage": "fetching_remote_metrics",
"current_stage_details": {},
"timestamps": {},
"stages": [],
"metric_progress": {},
"celery": {
"state": "STARTED",
"ready": false,
"successful": false,
"failed": false,
"info": {}
}
}
}
}
```
### response موفق `200` در حالت completed
```json
{
"code": 200,
"msg": "success",
"data": {
"status": "completed",
"source": "database",
"run": {},
"task_id": "11111111-1111-1111-1111-111111111111",
"task": {
"current_stage": "completed",
"current_stage_details": {},
"timestamps": {},
"stages": []
},
"location": {},
"block_code": "",
"chunk_size_sqm": 900,
"temporal_extent": {
"start_date": "2026-04-12",
"end_date": "2026-05-12"
},
"summary": {
"cell_count": 12,
"ndvi_mean": 0.54,
"ndwi_mean": 0.21,
"soil_vv_db_mean": -8.92
},
"cells": [],
"subdivision_result": {},
"pagination": {}
}
}
```
### توضیح فیلدهای `task`
- `current_stage`: stage فعلی pipeline
- `current_stage_details`: جزئیات همان stage
- `timestamps`: زمان ورود به stageها
- `stages`: تاریخچه stageها
- `metric_progress`: پیشرفت metricها هنگام fetch داده
- `retry`: اطلاعات retry اگر task در حال retry باشد
- `last_error`: آخرین خطا
- `failure_reason`: علت fail شدن task
- `celery.state`: وضعیت Celery مثل `PENDING`، `STARTED`، `RETRY`
- `celery.ready`: آیا task تمام شده
- `celery.successful`: آیا task موفق بوده
- `celery.failed`: آیا task fail شده
- `celery.info`: اطلاعات خام Celery
### مقادیر متداول `status`
- `pending`
- `running`
- `retrying`
- `completed`
- `failed`
### `404`
```json
{
"code": 404,
"msg": "run با این task_id پیدا نشد.",
"data": null
}
```
## 12) نکات مهم برای فرانت
- در همه endpointها اول `code` و بعد `data` را چک کنید.
- در `POST /remote-sensing/` همیشه انتظار `task_id` داشته باشید.
- در `POST /remote-sensing/` اگر داده قبلا موجود باشد هم ممکن است `202` بگیرید، چون سیستم برای polling یک run قابل پیگیری می‌سازد.
- در `GET /remote-sensing/runs/{run_id}/status/` اگر `status = completed` شد، همان response نهایی را استفاده کنید و دیگر لازم نیست `GET /remote-sensing/` را دوباره صدا بزنید.
- در `GET /remote-sensing/cluster-blocks/{cluster_uuid}/live/` مقدار `source` مهم است:
- `database`: از cache
- `openeo`: از backend زنده
- در responseهای subdivision، pagination ممکن است هم برای `cells` باشد و هم برای `assignments`.
## 13) محل فایل
این مستند در این مسیر ذخیره شده است:
- `docs/location_data_api_responses_fa.md`