Files
Logic/Modules/Backend/farm_hub/API_REFERENCE_FA.md
T

919 lines
22 KiB
Markdown
Raw Normal View History

2026-05-11 03:27:21 +03:30
# مستندات کامل API های `farm_hub`
این فایل بر اساس پیاده‌سازی واقعی اپ `farm_hub` در فایل‌های `farm_hub/urls.py`, `farm_hub/views.py`, `farm_hub/serializers.py`, `farm_hub/models.py` و `farm_hub/services.py` تهیه شده است.
نکته مهم: فایل `farm_hub/apps.py` فقط برای ثبت Django app استفاده می‌شود و خودِ APIها داخل آن تعریف نشده‌اند. APIهای این ماژول در `farm_hub/urls.py` و `farm_hub/views.py` قرار دارند.
## مشخصات کلی
- Base path:
```text
/api/farm-hub/
```
- احراز هویت:
تمام endpointهای این ماژول نیاز به کاربر لاگین‌شده دارند.
```http
Authorization: Bearer <token>
```
- فرمت کلی پاسخ موفق:
```json
{
"code": 200,
"msg": "success",
"data": {}
}
```
- فرمت کلی پاسخ خطا:
```json
{
"code": 404,
"msg": "Farm not found."
}
```
یا در خطاهای validation:
```json
{
"field_name": [
"error message"
]
}
```
## لیست endpointها
| Method | URL | توضیح |
|---|---|---|
| GET | `/api/farm-hub/` | دریافت لیست مزارع کاربر جاری |
| POST | `/api/farm-hub/` | ساخت مزرعه جدید |
| GET | `/api/farm-hub/farm-types/` | دریافت لیست نوع مزرعه‌ها |
| GET | `/api/farm-hub/farm-types/{farm_type_uuid}/products/` | دریافت محصولات مربوط به یک نوع مزرعه |
| GET | `/api/farm-hub/{farm_uuid}/` | دریافت جزئیات یک مزرعه |
| PATCH | `/api/farm-hub/{farm_uuid}/` | ویرایش مزرعه |
| DELETE | `/api/farm-hub/{farm_uuid}/` | حذف مزرعه |
| POST | `/api/farm-hub/active/` | فعال‌کردن مزرعه |
| POST | `/api/farm-hub/deactive/` | غیرفعال‌کردن مزرعه |
---
## 1) دریافت لیست مزارع
### Request
```http
GET /api/farm-hub/
Authorization: Bearer <token>
```
### رفتار
- فقط مزارع متعلق به کاربر جاری برگردانده می‌شوند.
- برای هر مزرعه، اطلاعات `farm_type`، لیست `products`، لیست `sensors` و `area_uuid` برگردانده می‌شود.
### Response 200
```json
{
"code": 200,
"msg": "success",
"data": [
{
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
"area_uuid": "0c7dfd7f-94bf-46f3-b2f9-30a89f0a1111",
"name": "مزرعه شماره 1",
"is_active": true,
"farm_type": {
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "زراعی",
"description": "",
"metadata": {}
},
"products": [
{
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "گندم",
"description": "",
"metadata": {},
"light": "",
"watering": "",
"soil": "",
"temperature": "",
"planting_season": "پاییز",
"harvest_time": "بهار",
"spacing": "",
"fertilizer": "",
"health_profile": {
"moisture": {
"ideal_value": 65
}
},
"irrigation_profile": {},
"growth_profile": {}
}
],
"sensors": [
{
"uuid": "33333333-3333-3333-3333-333333333333",
"sensor_catalog_uuid": "44444444-4444-4444-4444-444444444444",
"physical_device_uuid": "55555555-5555-5555-5555-555555555555",
"name": "Station 1",
"sensor_type": "weather_station",
"is_active": true,
"specifications": {
"model": "FH-1"
},
"power_source": {
"type": "battery"
},
"last_updated": "2025-02-18T12:00:00Z"
}
],
"last_updated": "2025-02-18T12:00:00Z"
}
]
}
```
---
## 2) ساخت مزرعه جدید
### Request
```http
POST /api/farm-hub/
Authorization: Bearer <token>
Content-Type: application/json
```
### Body
```json
{
"name": "مزرعه شماره 1",
"is_active": true,
"farm_type_uuid": "11111111-1111-1111-1111-111111111111",
"product_uuids": [
"22222222-2222-2222-2222-222222222222"
],
"sensors": [
{
"sensor_catalog_uuid": "44444444-4444-4444-4444-444444444444",
"physical_device_uuid": "55555555-5555-5555-5555-555555555555",
"name": "Station 1",
"sensor_type": "weather_station",
"is_active": true,
"specifications": {
"model": "FH-1"
},
"power_source": {
"type": "battery"
}
}
],
"farm_boundary": {
"corners": [
{"lat": 35.70, "lon": 51.39},
{"lat": 35.70, "lon": 51.41},
{"lat": 35.72, "lon": 51.41},
{"lat": 35.72, "lon": 51.39}
]
},
"sensor_key": "sensor-7-1",
"sensor_payload": {
"soil_moisture": 45.2,
"soil_temperature": 22.5
},
"irrigation_method_id": 3
}
```
برای `farm_boundary` هر دو فرم زیر پشتیبانی می‌شوند:
```json
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[51.418934, 35.706815],
[51.423054, 35.691062],
[51.384258, 35.689389],
[51.418934, 35.706815]
]
]
}
}
```
### فیلدهای ورودی
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
| `name` | string | بله | نام مزرعه |
| `is_active` | boolean | خیر | وضعیت فعال بودن مزرعه؛ پیش‌فرض مدل `true` است |
| `farm_type_uuid` | uuid | بله | UUID نوع مزرعه |
| `product_uuids` | array[uuid] | بله | لیست UUID محصولات؛ خالی بودن مجاز نیست |
| `sensors` | array | خیر | لیست سنسورهای مزرعه |
| `area_geojson` | object | خیر | محدوده زمین به صورت GeoJSON از نوع `Polygon`؛ اگر `farm_boundary` هم ارسال شود، این فیلد override می‌شود |
| `farm_boundary` | object | خیر | alias برای محدوده مزرعه؛ هم `Polygon` و هم فرم `corners` را می‌پذیرد |
| `sensor_key` | string | خیر | کلید سنسور برای normalize کردن `sensor_payload`؛ پیش فرض `sensor-7-1` |
| `sensor_payload` | object | خیر | داده سنسور که همراه ساخت مزرعه به Farm Data sync می‌شود |
| `irrigation_method_id` | integer/null | خیر | شناسه روش آبیاری که همراه ساخت مزرعه به Farm Data sync می‌شود |
### فیلدهای هر سنسور در `sensors`
| فیلد | نوع | اجباری | توضیح |
|---|---|---|---|
| `sensor_catalog_uuid` | uuid | خیر | اگر ارسال شود باید در `SensorCatalog` وجود داشته باشد |
| `physical_device_uuid` | uuid | خیر | شناسه دستگاه فیزیکی؛ اگر داده نشود مدل خودش مقدار تولید می‌کند |
| `name` | string | وابسته به ورودی | نام سنسور؛ اگر `sensor_catalog_uuid` معتبر باشد و `name` نفرستید، از نام catalog استفاده می‌شود، ولی اگر `sensor_catalog_uuid` هم نداشته باشید عملا باید `name` را بفرستید |
| `sensor_type` | string | خیر | نوع سنسور |
| `is_active` | boolean | خیر | وضعیت فعال بودن سنسور |
| `specifications` | object | خیر | مشخصات فنی |
| `power_source` | object | خیر | نوع یا جزئیات منبع تغذیه |
### اعتبارسنجی‌ها
- `farm_uuid` اگر از سمت کلاینت ارسال شود نادیده گرفته می‌شود.
- اگر `farm_boundary` به فرم `corners` ارسال شود، به Polygon تبدیل می‌شود.
- `sensor_payload` باید object باشد، وگرنه خطای validation برمی‌گردد.
- `farm_type_uuid` باید معتبر باشد، وگرنه:
```json
{
"farm_type_uuid": [
"Farm type not found."
]
}
```
- `product_uuids` باید همگی وجود داشته باشند:
```json
{
"product_uuids": [
"One or more products were not found."
]
}
```
- همه محصولات باید متعلق به همان `farm_type` باشند:
```json
{
"product_uuids": [
"Products must belong to farm type `زراعی`."
]
}
```
- `sensor_catalog_uuid` اگر ارسال شود باید معتبر باشد:
```json
{
"sensors": [
{
"sensor_catalog_uuid": [
"Sensor catalog not found."
]
}
]
}
```
### رفتار داخلی
- بعد از ساخت مزرعه و zoning، backend درخواست `POST /api/farm-data/` را نیز با `farm_uuid`، `farm_boundary`، `plant_ids` و در صورت وجود `sensor_payload`/`irrigation_method_id` ارسال می‌کند.
- اگر sync با Farm Data شکست بخورد، پاسخ endpoint با کد `502` برمی‌گردد.
- `area_geojson` باید object معتبر باشد.
- اگر `area_geojson.type == "Feature"` باشد، مقدار `geometry` بررسی می‌شود.
- `geometry.type` فقط باید `Polygon` باشد.
- `coordinates` باید ساختار polygon ring داشته باشد.
نمونه خطاهای `area_geojson`:
```json
{
"area_geojson": [
"`area_geojson` must be a GeoJSON object."
]
}
```
```json
{
"area_geojson": [
"`area_geojson.geometry.type` must be `Polygon`."
]
}
```
### رفتار داخلی مهم
- اگر `area_geojson` ارسال نشود، سیستم از `get_default_area_feature()` استفاده می‌کند.
- بعد از ساخت مزرعه، فرآیند zoning اجرا می‌شود.
- خروجی zoning به `current_crop_area` وصل می‌شود.
- اگر zoning با موفقیت ساخته شود، در response فیلد `zoning` هم برگردانده می‌شود.
### Response 201
```json
{
"code": 201,
"msg": "success",
"data": {
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
"area_uuid": "0c7dfd7f-94bf-46f3-b2f9-30a89f0a1111",
"name": "مزرعه شماره 1",
"is_active": true,
"farm_type": {
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "زراعی",
"description": "",
"metadata": {}
},
"products": [
{
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "گندم",
"description": "",
"metadata": {},
"light": "",
"watering": "",
"soil": "",
"temperature": "",
"planting_season": "پاییز",
"harvest_time": "بهار",
"spacing": "",
"fertilizer": "",
"health_profile": {},
"irrigation_profile": {},
"growth_profile": {}
}
],
"sensors": [
{
"uuid": "33333333-3333-3333-3333-333333333333",
"sensor_catalog_uuid": "44444444-4444-4444-4444-444444444444",
"physical_device_uuid": "55555555-5555-5555-5555-555555555555",
"name": "Station 1",
"sensor_type": "weather_station",
"is_active": true,
"specifications": {
"model": "FH-1"
},
"power_source": {
"type": "battery"
},
"last_updated": "2025-02-18T12:00:00Z"
}
],
"last_updated": "2025-02-18T12:00:00Z",
"zoning": {
"zone_count": 4
}
}
}
```
### Response 500
در صورتی که سرویس لازم برای zoning/config به‌درستی تنظیم نشده باشد:
```json
{
"code": 500,
"msg": "..."
}
```
---
## 3) دریافت لیست نوع مزرعه‌ها
### Request
```http
GET /api/farm-hub/farm-types/
Authorization: Bearer <token>
```
### Response 200
```json
{
"code": 200,
"msg": "success",
"data": [
{
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "زراعی",
"description": "",
"metadata": {}
},
{
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "درختی",
"description": "",
"metadata": {}
}
]
}
```
### نکته
- خروجی بر اساس `name` مرتب می‌شود.
---
## 4) دریافت محصولات یک نوع مزرعه
### Request
```http
GET /api/farm-hub/farm-types/{farm_type_uuid}/products/
Authorization: Bearer <token>
```
### Path Params
| پارامتر | نوع | توضیح |
|---|---|---|
| `farm_type_uuid` | uuid | شناسه نوع مزرعه |
### Response 200
```json
{
"code": 200,
"msg": "success",
"data": [
{
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "گندم",
"description": "",
"metadata": {},
"light": "",
"watering": "",
"soil": "",
"temperature": "",
"planting_season": "پاییز",
"harvest_time": "بهار",
"spacing": "",
"fertilizer": "",
"health_profile": {
"moisture": {
"ideal_value": 65
}
},
"irrigation_profile": {},
"growth_profile": {}
}
]
}
```
### Response 404
```json
{
"code": 404,
"msg": "Farm type not found."
}
```
### نکته
- محصولات با ترتیب `name` برگردانده می‌شوند.
---
## 5) دریافت جزئیات یک مزرعه
### Request
```http
GET /api/farm-hub/{farm_uuid}/
Authorization: Bearer <token>
```
### Path Params
| پارامتر | نوع | توضیح |
|---|---|---|
| `farm_uuid` | uuid | شناسه مزرعه |
### رفتار
- فقط اگر مزرعه متعلق به کاربر جاری باشد برگردانده می‌شود.
- اگر UUID وجود داشته باشد ولی متعلق به کاربر دیگری باشد، عملا مثل not found رفتار می‌شود.
### Response 200
ساختار `data` دقیقا مثل آیتم‌های خروجی لیست مزرعه‌ها است.
### Response 404
```json
{
"code": 404,
"msg": "Farm not found."
}
```
---
## 6) ویرایش مزرعه
### Request
```http
PATCH /api/farm-hub/{farm_uuid}/
Authorization: Bearer <token>
Content-Type: application/json
```
### Path Params
| پارامتر | نوع | توضیح |
|---|---|---|
| `farm_uuid` | uuid | شناسه مزرعه |
### Body
این endpoint از `partial update` استفاده می‌کند؛ یعنی می‌توانید فقط بخشی از فیلدها را بفرستید.
نمونه:
```json
{
"name": "مزرعه اصلاح شده",
"is_active": false,
"farm_type_uuid": "11111111-1111-1111-1111-111111111111",
"product_uuids": [
"22222222-2222-2222-2222-222222222222"
],
"sensors": [
{
"sensor_catalog_uuid": "44444444-4444-4444-4444-444444444444",
"physical_device_uuid": "55555555-5555-5555-5555-555555555555",
"name": "Station Updated",
"sensor_type": "weather_station",
"is_active": true,
"specifications": {
"model": "FH-2"
},
"power_source": {
"type": "solar"
}
}
],
"farm_boundary": {
"corners": [
{"lat": 35.70, "lon": 51.39},
{"lat": 35.70, "lon": 51.41},
{"lat": 35.72, "lon": 51.41},
{"lat": 35.72, "lon": 51.39}
]
},
"sensor_payload": {
"soil_moisture": 45.2
},
"irrigation_method_id": 3
}
```
### رفتار update
- `name` و `is_active` در صورت ارسال تغییر می‌کنند.
- اگر `farm_type_uuid` ارسال شود، نوع مزرعه به‌روزرسانی می‌شود.
- اگر `product_uuids` ارسال شود، همه محصولات مزرعه با لیست جدید جایگزین می‌شوند.
- اگر `sensors` ارسال شود، همه سنسورهای قبلی حذف و سپس سنسورهای جدید از نو ساخته می‌شوند.
- اگر `area_geojson` یا `farm_boundary` ارسال شود، zoning مجدد انجام می‌شود و `current_crop_area` به‌روزرسانی می‌شود.
- در هر update نیز درخواست sync به `POST /api/farm-data/` با `farm_uuid`، `farm_boundary`، `plant_ids` و در صورت وجود `sensor_payload`/`irrigation_method_id` ارسال می‌شود.
### اعتبارسنجی
همان قوانین create اینجا هم برقرار است، با این تفاوت:
- در update، اگر `farm_type_uuid` ارسال نشود، از `farm_type` فعلی استفاده می‌شود.
- در update، اگر `product_uuids` ارسال نشود، محصولات فعلی حفظ می‌شوند.
- در update، اگر `sensors` ارسال نشود، سنسورهای فعلی حفظ می‌شوند.
- در update نیز `sensor_payload` باید object باشد.
### Response 200
```json
{
"code": 200,
"msg": "success",
"data": {
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
"area_uuid": "0c7dfd7f-94bf-46f3-b2f9-30a89f0a1111",
"name": "مزرعه اصلاح شده",
"is_active": false,
"farm_type": {
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "زراعی",
"description": "",
"metadata": {}
},
"products": [],
"sensors": [],
"last_updated": "2025-02-18T13:00:00Z"
}
}
```
### Response 404
```json
{
"code": 404,
"msg": "Farm not found."
}
```
### Response 502
```json
{
"code": 502,
"msg": "Farm data API returned status 400: ..."
}
```
---
## 7) حذف مزرعه
### Request
```http
DELETE /api/farm-hub/{farm_uuid}/
Authorization: Bearer <token>
```
### Response 200
```json
{
"code": 200,
"msg": "success"
}
```
### Response 404
```json
{
"code": 404,
"msg": "Farm not found."
}
```
### نکته
- فقط مزرعه متعلق به کاربر جاری حذف می‌شود.
---
## 8) فعال‌کردن مزرعه
### Request
```http
POST /api/farm-hub/active/
Authorization: Bearer <token>
Content-Type: application/json
```
### Body
```json
{
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000"
}
```
### Response 200
```json
{
"code": 200,
"msg": "success"
}
```
### Response 404
```json
{
"code": 404,
"msg": "Farm not found."
}
```
### خطای validation
اگر `farm_uuid` ارسال نشود یا فرمت آن درست نباشد، خطای serializer برگردانده می‌شود. نمونه:
```json
{
"farm_uuid": [
"This field is required."
]
}
```
---
## 9) غیرفعال‌کردن مزرعه
### Request
```http
POST /api/farm-hub/deactive/
Authorization: Bearer <token>
Content-Type: application/json
```
### Body
```json
{
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000"
}
```
### Response 200
```json
{
"code": 200,
"msg": "success"
}
```
### Response 404
```json
{
"code": 404,
"msg": "Farm not found."
}
```
---
## ساختار آبجکت‌ها
## آبجکت `FarmType`
```json
{
"uuid": "11111111-1111-1111-1111-111111111111",
"name": "زراعی",
"description": "",
"metadata": {}
}
```
## آبجکت `Product`
```json
{
"uuid": "22222222-2222-2222-2222-222222222222",
"name": "گندم",
"description": "",
"metadata": {},
"light": "",
"watering": "",
"soil": "",
"temperature": "",
"planting_season": "",
"harvest_time": "",
"spacing": "",
"fertilizer": "",
"health_profile": {},
"irrigation_profile": {},
"growth_profile": {}
}
```
### توضیح فیلدهای پروفایل محصول
- `health_profile`: برای KPIها و سلامت محصول
- `irrigation_profile`: برای محاسبات آبیاری و ETc
- `growth_profile`: برای مدل رشد مانند GDD
نمونه ساختار `health_profile`:
```json
{
"moisture": {
"ideal_value": 65,
"min_range": 45,
"max_range": 75,
"weight": 0.4
}
}
```
نمونه ساختار `irrigation_profile`:
```json
{
"kc_initial": 0.6,
"kc_mid": 1.15,
"kc_end": 0.8,
"growth_stage_duration": {
"initial": 20,
"mid": 30,
"late": 25
}
}
```
نمونه ساختار `growth_profile`:
```json
{
"base_temperature": 10,
"required_gdd_for_maturity": 1200,
"stage_thresholds": {
"flowering": 500,
"fruiting": 850
},
"current_cumulative_gdd": 320
}
```
## آبجکت `FarmSensor`
```json
{
"uuid": "33333333-3333-3333-3333-333333333333",
"sensor_catalog_uuid": "44444444-4444-4444-4444-444444444444",
"physical_device_uuid": "55555555-5555-5555-5555-555555555555",
"name": "Station 1",
"sensor_type": "weather_station",
"is_active": true,
"specifications": {},
"power_source": {},
"last_updated": "2025-02-18T12:00:00Z"
}
```
## آبجکت `FarmHub`
```json
{
"farm_uuid": "550e8400-e29b-41d4-a716-446655440000",
"area_uuid": "0c7dfd7f-94bf-46f3-b2f9-30a89f0a1111",
"name": "مزرعه شماره 1",
"is_active": true,
"farm_type": {},
"products": [],
"sensors": [],
"last_updated": "2025-02-18T12:00:00Z"
}
```
---
## نکات مهم برای فرانت‌اند
- برای ساخت مزرعه، ابتدا `GET /api/farm-hub/farm-types/` را صدا بزنید.
- سپس برای نوع انتخاب‌شده، `GET /api/farm-hub/farm-types/{farm_type_uuid}/products/` را بگیرید.
- برای ساخت یا ویرایش مزرعه، `product_uuids` باید با `farm_type_uuid` هم‌خوانی داشته باشند.
- اگر در update فیلد `sensors` را بفرستید، لیست قبلی کامل جایگزین می‌شود.
- اگر در create، `area_geojson` نفرستید، سیستم خودش یک محدوده پیش‌فرض می‌سازد.
- endpointهای detail/update/delete/active/deactive فقط روی مزرعه‌های خود کاربر عمل می‌کنند.
---
## منبع پیاده‌سازی
- رجیستر اپ: `farm_hub/apps.py`
- تعریف routeها: `farm_hub/urls.py`
- منطق APIها: `farm_hub/views.py`
- serializerها و validation: `farm_hub/serializers.py`
- مدل‌ها: `farm_hub/models.py`
- منطق ساخت zoning: `farm_hub/services.py`
- نمونه requestها: `farm_hub/postman/farm_hub.json`