Files
Backend/docs/location_data_api_responses_fa.md
2026-05-13 22:29:18 +03:30

23 KiB

مستند کامل 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 را دارند:

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

توضیح فیلدها:

  • code: کد منطقی response در body
  • msg: پیام کوتاه
  • data: payload اصلی

در خطاها معمولا یکی از این دو حالت برمی‌گردد:

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "field_name": ["error message"]
  }
}

یا:

{
  "code": 404,
  "msg": "location پیدا نشد.",
  "data": null
}

2) GET /api/location-data/

کاربرد:

  • خواندن ساختار ذخیره‌شده مزرعه
  • خواندن بلوک‌ها
  • خواندن subdivisionها
  • خواندن snapshotهای ماهواره‌ای ذخیره/تجمیع‌شده

response موفق 200

{
  "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

{
  "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 نامعتبر باشد:

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "lat": ["..."],
    "lon": ["..."]
  }
}

404

وقتی location پیدا نشود:

{
  "code": 404,
  "msg": "location پیدا نشد.",
  "data": null
}

3) POST /api/location-data/

کاربرد:

  • ثبت یا به‌روزرسانی مزرعه
  • ثبت مرز مزرعه
  • ثبت بلوک‌های کشاورز

response موفق 200

{
  "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 نامعتبر باشد:

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "farm_boundary": ["مختصات گوشه‌های کل زمین باید ارسال شود."]
  }
}

حالت دوم: مرز کل مزرعه نه در request آمده و نه قبلا ذخیره شده:

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "farm_boundary": [
      "برای ثبت location باید گوشه‌های کل زمین ارسال یا قبلاً ذخیره شده باشد."
    ]
  }
}

4) POST /api/location-data/ndvi-health/

کاربرد:

  • برگرداندن وضعیت سلامت پوشش گیاهی مزرعه بر اساس NDVI

response موفق 200

{
  "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

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "farm_uuid": ["..."]
  }
}

404

{
  "code": 404,
  "msg": "مزرعه پیدا نشد.",
  "data": null
}

5) GET /api/location-data/remote-sensing/

کاربرد:

  • فقط نتایج cache شده remote sensing و subdivision را می‌خواند
  • هیچ پردازش جدیدی اجرا نمی‌کند

response موفق 200

{
  "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

{
  "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

{
  "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

{
  "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

{
  "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

{
  "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

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "farm_uuid": ["..."]
  }
}

404

{
  "code": 404,
  "msg": "location پیدا نشد.",
  "data": null
}

6) POST /api/location-data/remote-sensing/

کاربرد:

  • اجرای async تحلیل سنجش‌ازدور
  • ساخت run و task قابل polling
  • اگر داده قبلا در DB موجود باشد هم یک task_id tracking برمی‌گرداند تا status بلافاصله نتیجه را بدهد

response موفق 202

{
  "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

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "farm_uuid": ["..."]
  }
}

404

{
  "code": 404,
  "msg": "location پیدا نشد.",
  "data": null
}

7) GET /api/location-data/remote-sensing/cluster-blocks/{cluster_uuid}/live/

کاربرد:

  • دریافت metricهای زنده یا cache شده برای یک cluster block

response موفق 200

{
  "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 معتبر نباشد

نمونه:

{
  "code": 400,
  "msg": "هندسه زیر‌بلاک KMeans نامعتبر است.",
  "data": {
    "cluster_uuid": ["11111111-1111-1111-1111-111111111111"]
  }
}

404

{
  "code": 404,
  "msg": "زیر‌بلاک KMeans پیدا نشد.",
  "data": null
}

502

وقتی openEO پاسخ ندهد:

{
  "code": 502,
  "msg": "خواندن داده از openEO ناموفق بود.",
  "data": {
    "detail": "..."
  }
}

8) GET /api/location-data/remote-sensing/cluster-recommendations/

کاربرد:

  • مقایسه گیاه‌های ثبت‌شده در farm_data
  • استفاده از داده کلاسترها
  • استفاده از crop_simulation
  • پیشنهاد بهترین گیاه برای هر cluster

response موفق 200

{
  "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

{
  "plant_id": 101,
  "plant_name": "Tomato",
  "position": 0,
  "stage": "vegetative"
}

ساختار هر آیتم clusters

{
  "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

{
  "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 کامل نباشد:

{
  "code": 400,
  "msg": "برای این مزرعه هنوز هیچ گیاهی در farm_data ثبت نشده است.",
  "data": null
}

404

وقتی مزرعه یا خروجی KMeans پیدا نشود:

{
  "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

{
  "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

{
  "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

{
  "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

{
  "code": 404,
  "msg": "subdivision result پیدا نشد.",
  "data": null
}

10) POST /api/location-data/remote-sensing/results/{result_id}/k-options/activate/

کاربرد:

  • فعال‌سازی یکی از Kهای ذخیره‌شده

response موفق 200

{
  "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 نامعتبر

{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "requested_k": ["..."]
  }
}

حالت دوم: K داخل optionها وجود ندارد

{
  "code": 400,
  "msg": "K انتخابی برای این subdivision result موجود نیست.",
  "data": {
    "requested_k": [7]
  }
}

404

{
  "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

{
  "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

{
  "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

{
  "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