UPDATE
This commit is contained in:
@@ -0,0 +1,594 @@
|
||||
# مستند 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` داشته باشند
|
||||
|
||||
Reference in New Issue
Block a user