595 lines
16 KiB
Markdown
595 lines
16 KiB
Markdown
# مستند API سنسورها برای فرانت
|
|
|
|
این فایل قرارداد پیشنهادی/هدف برای endpointهای سنسوری زیر است و بر اساس نیاز اعلامشده تهیه شده است:
|
|
|
|
- `GET /api/sensor-7-in-1/summary/`
|
|
- `GET /api/sensors/comparison-chart/`
|
|
- `GET /api/sensors/radar-chart/`
|
|
- `GET /api/sensors/values-list/`
|
|
- `GET /api/sensor-external-api/logs/`
|
|
|
|
نکته مهم:
|
|
|
|
- این سند بر اساس نیاز محصول و قرارداد موردنظر فرانت نوشته شده است.
|
|
- در این قرارداد دیگر `physical_device_uuid` از فرانت گرفته نمیشود.
|
|
- مبنای جستوجو فقط `farm_uuid` است.
|
|
- backend باید با استفاده از `farm_uuid`، رکورد مزرعه را پیدا کند و اولین سنسور خاک را بهعنوان سنسور مبنا انتخاب کند.
|
|
- اگر `range` ارسال نشود، backend باید بدون خطا مقدار پیشفرض `7` روز را در نظر بگیرد.
|
|
|
|
---
|
|
|
|
## 1) قواعد عمومی
|
|
|
|
### آدرس پایه
|
|
|
|
- پیشوند تمام مسیرها: `/api/`
|
|
|
|
### فرمت پاسخ
|
|
|
|
همه endpointها بهتر است envelope استاندارد زیر را برگردانند:
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {}
|
|
}
|
|
```
|
|
|
|
### پارامترهای مشترک
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض: `7`
|
|
|
|
### رفتار `range`
|
|
|
|
- اگر `range` ارسال نشده باشد: backend باید `7` را استفاده کند.
|
|
- اگر `range` کمتر از `1` باشد: بهتر است `400` برگردد.
|
|
- اگر `range` خیلی بزرگ باشد: پیشنهاد میشود backend آن را محدود کند، مثلا حداکثر `90`.
|
|
|
|
نمونه:
|
|
|
|
- `/api/sensor-7-in-1/summary/?farm_uuid=11111111-1111-1111-1111-111111111111`
|
|
- `/api/sensors/comparison-chart/?farm_uuid=11111111-1111-1111-1111-111111111111&range=30`
|
|
|
|
### منطق انتخاب سنسور
|
|
|
|
با دریافت `farm_uuid`:
|
|
|
|
1. رکورد `farm_data.SensorData` پیدا میشود.
|
|
2. از `sensor_payload` اولین سنسور خاک انتخاب میشود.
|
|
3. اگر چند سنسور موجود باشد، اولویت پیشنهادی:
|
|
- اولین کلیدی که با `sensor-7` یا `sensor-7-in-1` شروع میشود
|
|
- اگر نبود، اولین block معتبر از نوع object
|
|
4. همان سنسور برای ساخت summary، chart و values استفاده میشود.
|
|
|
|
### خطاهای مشترک
|
|
|
|
#### 400 — ورودی نامعتبر
|
|
|
|
```json
|
|
{
|
|
"code": 400,
|
|
"msg": "داده نامعتبر.",
|
|
"data": {
|
|
"farm_uuid": [
|
|
"This field is required."
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
یا:
|
|
|
|
```json
|
|
{
|
|
"code": 400,
|
|
"msg": "داده نامعتبر.",
|
|
"data": {
|
|
"range": [
|
|
"range باید عددی بزرگتر از صفر باشد."
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 404 — مزرعه یا سنسور پیدا نشد
|
|
|
|
```json
|
|
{
|
|
"code": 404,
|
|
"msg": "farm یا سنسور خاک یافت نشد.",
|
|
"data": null
|
|
}
|
|
```
|
|
|
|
#### 200 — بدون داده کافی
|
|
|
|
اگر مزرعه وجود داشته باشد ولی history کافی برای بازه در دسترس نباشد، پیشنهاد میشود endpoint بهجای خطا، پاسخ موفق با `data` خالی یا حداقلی برگرداند.
|
|
|
|
---
|
|
|
|
## 2) GET /api/sensor-7-in-1/summary/
|
|
|
|
### هدف
|
|
|
|
نمایش خلاصه سریع آخرین وضعیت سنسور خاک انتخابشده برای یک مزرعه.
|
|
|
|
### Query Params
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض `7`
|
|
|
|
### منطق پاسخ
|
|
|
|
- آخرین reading سنسور انتخابشده نمایش داده میشود.
|
|
- اگر داده historical موجود باشد، trend نسبت به بازه `range` محاسبه میشود.
|
|
- این endpoint مناسب hero cards و summary cards فرانت است.
|
|
|
|
### پاسخ موفق نمونه
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {
|
|
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
|
"sensor_key": "sensor-7-1",
|
|
"range": 7,
|
|
"last_updated_at": "2026-04-29T10:20:00Z",
|
|
"summary": {
|
|
"soil_moisture": {
|
|
"label": "رطوبت خاک",
|
|
"value": 31.2,
|
|
"unit": "%",
|
|
"trend": "up",
|
|
"change": 2.1,
|
|
"change_unit": "%"
|
|
},
|
|
"soil_temperature": {
|
|
"label": "دمای خاک",
|
|
"value": 22.8,
|
|
"unit": "°C",
|
|
"trend": "stable",
|
|
"change": 0.3,
|
|
"change_unit": "°C"
|
|
},
|
|
"soil_ph": {
|
|
"label": "pH خاک",
|
|
"value": 6.9,
|
|
"unit": "",
|
|
"trend": "down",
|
|
"change": -0.1,
|
|
"change_unit": ""
|
|
},
|
|
"electrical_conductivity": {
|
|
"label": "هدایت الکتریکی",
|
|
"value": 1.4,
|
|
"unit": "mS/cm",
|
|
"trend": "stable",
|
|
"change": 0.0,
|
|
"change_unit": "mS/cm"
|
|
},
|
|
"nitrogen": {
|
|
"label": "نیتروژن",
|
|
"value": 28.0,
|
|
"unit": "mg/kg",
|
|
"trend": "up",
|
|
"change": 1.8,
|
|
"change_unit": "mg/kg"
|
|
},
|
|
"phosphorus": {
|
|
"label": "فسفر",
|
|
"value": 14.5,
|
|
"unit": "mg/kg",
|
|
"trend": "stable",
|
|
"change": 0.4,
|
|
"change_unit": "mg/kg"
|
|
},
|
|
"potassium": {
|
|
"label": "پتاسیم",
|
|
"value": 21.7,
|
|
"unit": "mg/kg",
|
|
"trend": "down",
|
|
"change": -0.9,
|
|
"change_unit": "mg/kg"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### فیلدهای خروجی
|
|
|
|
- `farm_uuid`: شناسه مزرعه
|
|
- `sensor_key`: کلید سنسور انتخابشده از `sensor_payload`
|
|
- `range`: بازه واقعی استفادهشده
|
|
- `last_updated_at`: زمان آخرین reading یا آخرین بهروزرسانی
|
|
- `summary`: آبجکت شامل KPIهای اصلی
|
|
|
|
### ساختار هر KPI
|
|
|
|
- `label`: عنوان فارسی
|
|
- `value`: آخرین مقدار
|
|
- `unit`: واحد
|
|
- `trend`: یکی از `up | down | stable | unknown`
|
|
- `change`: اختلاف با ابتدای بازه یا میانگین بازه
|
|
- `change_unit`: واحد اختلاف
|
|
|
|
---
|
|
|
|
## 3) GET /api/sensors/comparison-chart/
|
|
|
|
### هدف
|
|
|
|
برگرداندن داده chart مقایسهای برای چند پارامتر سنسور در طول بازه زمانی.
|
|
|
|
### Query Params
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض `7`
|
|
|
|
### منطق پاسخ
|
|
|
|
- فقط یک سنسور مبنا از روی `farm_uuid` انتخاب میشود.
|
|
- برای همان سنسور، سریهای چند متریک در طول بازه برگردانده میشود.
|
|
- فرانت میتواند آن را به line chart یا multi-series chart تبدیل کند.
|
|
|
|
### پاسخ موفق نمونه
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {
|
|
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
|
"sensor_key": "sensor-7-1",
|
|
"range": 7,
|
|
"categories": [
|
|
"2026-04-23",
|
|
"2026-04-24",
|
|
"2026-04-25",
|
|
"2026-04-26",
|
|
"2026-04-27",
|
|
"2026-04-28",
|
|
"2026-04-29"
|
|
],
|
|
"series": [
|
|
{
|
|
"key": "soil_moisture",
|
|
"label": "رطوبت خاک",
|
|
"unit": "%",
|
|
"data": [29.1, 28.7, 30.4, 30.0, 31.1, 31.0, 31.2]
|
|
},
|
|
{
|
|
"key": "soil_temperature",
|
|
"label": "دمای خاک",
|
|
"unit": "°C",
|
|
"data": [21.4, 21.8, 22.0, 22.1, 22.2, 22.6, 22.8]
|
|
},
|
|
{
|
|
"key": "electrical_conductivity",
|
|
"label": "هدایت الکتریکی",
|
|
"unit": "mS/cm",
|
|
"data": [1.2, 1.3, 1.3, 1.4, 1.4, 1.4, 1.4]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### فیلدهای خروجی
|
|
|
|
- `categories`: برچسبهای محور زمان
|
|
- `series`: آرایه سریها
|
|
|
|
### ساختار هر سری
|
|
|
|
- `key`: کلید متریک
|
|
- `label`: نام نمایشی
|
|
- `unit`: واحد
|
|
- `data`: آرایه مقادیر همطول با `categories`
|
|
|
|
---
|
|
|
|
## 4) GET /api/sensors/radar-chart/
|
|
|
|
### هدف
|
|
|
|
دادن داده مناسب radar chart برای مقایسه همزمان وضعیت متریکهای اصلی سنسور.
|
|
|
|
### Query Params
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض `7`
|
|
|
|
### منطق پاسخ
|
|
|
|
- برای هر متریک، یک مقدار خلاصه از بازه ساخته میشود؛ مثلا:
|
|
- آخرین مقدار
|
|
- میانگین بازه
|
|
- یا score نرمالشده 0 تا 100
|
|
- برای radar chart پیشنهاد میشود score نهایی نرمالشده برگردانده شود.
|
|
|
|
### پاسخ موفق نمونه
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {
|
|
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
|
"sensor_key": "sensor-7-1",
|
|
"range": 7,
|
|
"labels": [
|
|
"رطوبت خاک",
|
|
"دمای خاک",
|
|
"pH خاک",
|
|
"هدایت الکتریکی",
|
|
"نیتروژن",
|
|
"فسفر",
|
|
"پتاسیم"
|
|
],
|
|
"series": [
|
|
{
|
|
"name": "وضعیت فعلی",
|
|
"data": [72, 64, 81, 58, 69, 61, 74]
|
|
}
|
|
],
|
|
"raw_metrics": [
|
|
{
|
|
"key": "soil_moisture",
|
|
"label": "رطوبت خاک",
|
|
"value": 31.2,
|
|
"unit": "%",
|
|
"score": 72
|
|
},
|
|
{
|
|
"key": "soil_temperature",
|
|
"label": "دمای خاک",
|
|
"value": 22.8,
|
|
"unit": "°C",
|
|
"score": 64
|
|
},
|
|
{
|
|
"key": "soil_ph",
|
|
"label": "pH خاک",
|
|
"value": 6.9,
|
|
"unit": "",
|
|
"score": 81
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### فیلدهای خروجی
|
|
|
|
- `labels`: برچسبهای radar
|
|
- `series`: داده آماده برای chart
|
|
- `raw_metrics`: داده خام برای tooltip و جزئیات بیشتر
|
|
|
|
---
|
|
|
|
## 5) GET /api/sensors/values-list/
|
|
|
|
### هدف
|
|
|
|
برگرداندن لیست tabular از مقادیر سنسور برای بازه زمانی، مناسب table یا export.
|
|
|
|
### Query Params
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض `7`
|
|
|
|
### پاسخ موفق نمونه
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {
|
|
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
|
"sensor_key": "sensor-7-1",
|
|
"range": 7,
|
|
"count": 3,
|
|
"items": [
|
|
{
|
|
"recorded_at": "2026-04-29T10:20:00Z",
|
|
"soil_moisture": 31.2,
|
|
"soil_temperature": 22.8,
|
|
"soil_ph": 6.9,
|
|
"electrical_conductivity": 1.4,
|
|
"nitrogen": 28.0,
|
|
"phosphorus": 14.5,
|
|
"potassium": 21.7
|
|
},
|
|
{
|
|
"recorded_at": "2026-04-28T10:20:00Z",
|
|
"soil_moisture": 31.0,
|
|
"soil_temperature": 22.6,
|
|
"soil_ph": 7.0,
|
|
"electrical_conductivity": 1.4,
|
|
"nitrogen": 27.5,
|
|
"phosphorus": 14.1,
|
|
"potassium": 22.1
|
|
},
|
|
{
|
|
"recorded_at": "2026-04-27T10:20:00Z",
|
|
"soil_moisture": 31.1,
|
|
"soil_temperature": 22.2,
|
|
"soil_ph": 7.0,
|
|
"electrical_conductivity": 1.3,
|
|
"nitrogen": 27.2,
|
|
"phosphorus": 14.0,
|
|
"potassium": 22.6
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### فیلدهای خروجی
|
|
|
|
- `count`: تعداد رکوردها
|
|
- `items`: لیست ردیفها
|
|
- هر ردیف شامل timestamp و مقادیر متریکها
|
|
|
|
### رفتار پیشنهادی
|
|
|
|
- ترتیب رکوردها: جدید به قدیم
|
|
- اگر داده تاریخی نداریم ولی آخرین payload فعلی موجود است، حداقل یک item با آخرین وضعیت برگردانده شود
|
|
|
|
---
|
|
|
|
## 6) GET /api/sensor-external-api/logs/
|
|
|
|
### هدف
|
|
|
|
نمایش لاگهای مربوط به سینک یا واکشی داده سنسور از API بیرونی، مناسب صفحه monitoring یا audit.
|
|
|
|
### Query Params
|
|
|
|
- `farm_uuid` — `uuid string` — الزامی
|
|
- `range` — `integer` — اختیاری — پیشفرض `7`
|
|
|
|
### توضیح دامنه
|
|
|
|
این endpoint برای نمایش لاگهای integration است، نه لزوما readingهای سنسور.
|
|
|
|
اگر backend هنوز لاگ جداگانه برای external sensor sync نداشته باشد، پیشنهاد میشود ساختار زیر مبنای پیادهسازی قرار بگیرد.
|
|
|
|
### پاسخ موفق نمونه
|
|
|
|
```json
|
|
{
|
|
"code": 200,
|
|
"msg": "success",
|
|
"data": {
|
|
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
|
"range": 7,
|
|
"count": 4,
|
|
"items": [
|
|
{
|
|
"id": 104,
|
|
"status": "success",
|
|
"source": "sensor-external-api",
|
|
"sensor_key": "sensor-7-1",
|
|
"requested_at": "2026-04-29T10:20:00Z",
|
|
"finished_at": "2026-04-29T10:20:01Z",
|
|
"duration_ms": 842,
|
|
"http_status": 200,
|
|
"message": "داده سنسور با موفقیت واکشی شد."
|
|
},
|
|
{
|
|
"id": 103,
|
|
"status": "error",
|
|
"source": "sensor-external-api",
|
|
"sensor_key": "sensor-7-1",
|
|
"requested_at": "2026-04-28T10:20:00Z",
|
|
"finished_at": "2026-04-28T10:21:00Z",
|
|
"duration_ms": 60000,
|
|
"http_status": 504,
|
|
"message": "Timeout هنگام واکشی داده سنسور."
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### فیلدهای خروجی
|
|
|
|
- `status`: یکی از `success | error | timeout | partial`
|
|
- `source`: نام provider یا سرویس خارجی
|
|
- `requested_at`: زمان شروع درخواست
|
|
- `finished_at`: زمان پایان
|
|
- `duration_ms`: مدت زمان
|
|
- `http_status`: وضعیت HTTP سرویس بیرونی
|
|
- `message`: پیام خلاصه برای UI
|
|
|
|
---
|
|
|
|
## 7) رفتار پیشنهادی در نبود `range`
|
|
|
|
در همه endpointهای این سند:
|
|
|
|
- اگر `range` ارسال نشده باشد:
|
|
|
|
```json
|
|
{
|
|
"range": 7
|
|
}
|
|
```
|
|
|
|
باید بهصورت implicit استفاده شود و endpoint نباید خطای validation برگرداند.
|
|
|
|
---
|
|
|
|
## 8) رفتار پیشنهادی در نبود `physical_device_uuid`
|
|
|
|
فرانت نباید `physical_device_uuid` ارسال کند.
|
|
|
|
backend باید:
|
|
|
|
- فقط `farm_uuid` را بگیرد
|
|
- سنسور را از روی `sensor_payload` یا mapping داخلی انتخاب کند
|
|
- `sensor_key` نهایی را در پاسخ برگرداند تا فرانت بداند داده از کدام سنسور آمده است
|
|
|
|
---
|
|
|
|
## 9) پیشنهاد استاندارد برای متریکها
|
|
|
|
برای هماهنگی فرانت و بک، بهتر است حداقل این کلیدها در endpointها پشتیبانی شوند:
|
|
|
|
- `soil_moisture`
|
|
- `soil_temperature`
|
|
- `soil_ph`
|
|
- `electrical_conductivity`
|
|
- `nitrogen`
|
|
- `phosphorus`
|
|
- `potassium`
|
|
|
|
### واحدهای پیشنهادی
|
|
|
|
- `soil_moisture` → `%`
|
|
- `soil_temperature` → `°C`
|
|
- `soil_ph` → بدون واحد
|
|
- `electrical_conductivity` → `mS/cm`
|
|
- `nitrogen` → `mg/kg`
|
|
- `phosphorus` → `mg/kg`
|
|
- `potassium` → `mg/kg`
|
|
|
|
---
|
|
|
|
## 10) پیشنهاد برای وضعیتهای فرانت
|
|
|
|
### loading
|
|
|
|
- هنگام request، فرانت skeleton یا spinner نشان دهد
|
|
|
|
### empty
|
|
|
|
- اگر `items: []` یا `series: []` برگشت:
|
|
- پیام مناسب مثل `دادهای برای این بازه ثبت نشده است.` نمایش داده شود
|
|
|
|
### partial
|
|
|
|
- اگر بعضی متریکها `null` باشند:
|
|
- chart فقط seriesهای موجود را نمایش دهد
|
|
- در table برای فیلدهای خالی `—` نمایش داده شود
|
|
|
|
---
|
|
|
|
## 11) جمعبندی قرارداد
|
|
|
|
برای این 5 endpoint، قرارداد موردنیاز فرانت بهصورت خلاصه:
|
|
|
|
- ورودی اصلی فقط `farm_uuid`
|
|
- `physical_device_uuid` حذف شود
|
|
- `range` اختیاری باشد
|
|
- اگر `range` نیامد، مقدار پیشفرض `7` در نظر گرفته شود
|
|
- backend اولین سنسور خاک مزرعه را انتخاب کند
|
|
- `sensor_key` انتخابشده در response برگردانده شود
|
|
- responseها envelope استاندارد `code/msg/data` داشته باشند
|
|
|