13 KiB
پیشنهاد معماری سنسور برای Backend و AI
مسئله اصلی
تو سناریوی شما ممکن است:
- یک مزرعه چندین سنسور داشته باشد
- سنسورها از vendorهای مختلف باشند
- هر سنسور payload متفاوتی بفرستد
- بعضی سنسورها یک metric مشترک مثل
soil_moistureرا همزمان گزارش کنند - AI مجبور باشد هم raw data را بفهمد و هم یک view تجمیعشده برای recommendation داشته باشد
پس معماری سنسور باید این سه ویژگی را همزمان داشته باشد:
- انعطافپذیری در نوع سنسور
- قابلیت نگهداری چند سنسور برای یک farm
- قابلیت تبدیل raw sensor data به metricهای استاندارد برای AI
چیزی که الان در پروژه دارید
در Backend
Backend/farm_hub/models.pyمدلFarmSensorرا دارد برای register کردن سنسورهای هر مزرعهBackend/sensor_catalog/models.pyمدلSensorCatalogرا دارد برای تعریف نوع/کاتالوگ سنسورBackend/sensor_external_api/models.pyلاگ raw requestهای دستگاهها را نگه میدارد
یعنی Backend الان تا حد خوبی نقش device registry + ingestion gateway + audit log را دارد.
در AI
Ai/farm_data/models.py::SensorDataداده سنسورها را درsensor_payloadنگه میداردAi/farm_data/models.py::SensorParameterپارامترهای قابل پشتیبانی هرsensor_keyرا نگه میداردAi/farm_data/services.pyروی payloadهای چند سنسوره metric resolve میکند
یعنی AI الان نقش farm context store + normalized sensor context را دارد.
جمعبندی نقشها
به نظر من بهترین تفکیک این است:
Backend = owner دستگاه و جریان ورود داده
Backend باید مسئول اینها باشد:
- ثبت سنسور برای مزرعه
- نگهداری metadata دستگاه
- احراز هویت request دستگاه
- ثبت raw payload
- forward کردن داده به AI
AI = owner داده تحلیلی و context مزرعه
AI باید مسئول اینها باشد:
- نگهداری normalized view از داده سنسورها برای هر farm
- استانداردسازی metricها
- merge / aggregation / conflict resolution
- feed کردن irrigation / fertilization / crop simulation / alerts / RAG
پیشنهاد معماری نهایی
1) در Backend فقط registry و ingestion را canonical نگه دار
SensorCatalog
این جدول باید تعریفکننده template سنسور باشد:
codenamedescriptionreturned_data_fieldssample_payloadcustomizable_fieldssupported_power_sources
ولی بهتر است بعداً این metadataها را قویتر کنی:
measurement_schemasupported_metricspayload_mappingtransport_typeمثلhttp,mqtt,lorawanvendormodelfirmware_constraints
FarmSensor
این جدول باید instance واقعی دستگاه روی مزرعه باشد.
پیشنهاد فیلدهای مفهومی:
farmsensor_catalogphysical_device_uuidnamesensor_typeinstallation_zonedepth_cmpositionstatuslast_seen_atcalibrationspecificationspower_sourcemetadata
یعنی FarmSensor باید بگوید:
- این دستگاه چیست
- کجا نصب شده
- چه زمانی آخرین بار data فرستاده
- به چه farm تعلق دارد
2) در Backend raw event را جدا از registry نگه دار
الان SensorExternalRequestLog فقط لاگ request است. این خوب است، ولی برای مقیاسپذیری بهتر است دو لایه داشته باشی:
لایه اول: audit log
همان چیزی که الان داری:
- raw payload
- request time
- physical device uuid
- farm uuid
لایه دوم: normalized ingestion event
اگر بخواهی معماری تمیزتر شود، بهتر است یک مدل جدا هم داشته باشی، مثلاً:
SensorReadingEvent
که در آن اینها ذخیره شود:
farm_sensorrecorded_atreceived_atpayload_rawpayload_normalizedingestion_statusvalidation_errors
این مدل لازم نیست الان فوراً ساخته شود، ولی اگر سنسورها زیاد شوند خیلی کمک میکند.
3) در AI داده سنسورها را به شکل sensor-centric نگه دار، نه فقط metric-centric
الان Ai/farm_data/models.py::SensorData این ساختار را دارد:
{
"sensor-7-1": {
"soil_moisture": 22.4,
"soil_temperature": 18.1
},
"leaf-sensor": {
"leaf_wetness": 11
}
}
این از نظر انعطافپذیری خوب است، ولی یک ضعف دارد:
sensor_keyبیشتر نوع سنسور را نشان میدهد، نه instance سنسور
اگر یک farm دو سنسور از یک type داشته باشد، این ساختار collision میدهد.
پیشنهاد بهتر
در AI payload را بر اساس sensor instance نگه دار، نه فقط type:
{
"device:8c1e...": {
"sensor_key": "sensor-7-1",
"sensor_type": "soil_probe",
"recorded_at": "2026-05-02T10:15:00Z",
"metrics": {
"soil_moisture": 22.4,
"soil_temperature": 18.1
},
"metadata": {
"depth_cm": 20,
"zone": "north-1"
}
},
"device:91af...": {
"sensor_key": "sensor-7-1",
"sensor_type": "soil_probe",
"recorded_at": "2026-05-02T10:15:30Z",
"metrics": {
"soil_moisture": 24.1,
"soil_temperature": 17.9
},
"metadata": {
"depth_cm": 40,
"zone": "north-1"
}
}
}
یعنی key اصلی بهتر است یکی از اینها باشد:
physical_device_uuid- یا
farm_sensor.uuid
نه فقط sensor-7-1.
4) در AI یک لایه normalized metrics جدا بساز
AI برای recommendation نباید هر بار raw payload را از صفر تفسیر کند.
بهترین مدل ذهنی این است:
لایه A: raw sensor context
- هر sensor instance چه چیزی فرستاده؟
لایه B: resolved farm metrics
- برای farm در این لحظه
soil_moistureنهایی چقدر است؟ - source این metric کدام sensorها بوده؟
- strategy حل conflict چه بوده؟
الان Ai/farm_data/services.py بخشی از این کار را انجام میدهد. این مسیر درست است.
پیشنهاد من:
sensor_payload= raw/near-raw normalized by deviceresolved_metrics= خروجی استاندارد شده برای AImetric_sources= توضیح اینکه هر metric از کجا آمده
اینها لازم نیست حتماً همگی DB column جدا باشند؛ فعلاً میتوانند در service layer ساخته شوند. ولی از نظر معماری باید explicit باشند.
5) resolution strategy باید قابل تنظیم باشد
وقتی چند سنسور یک metric مشترک دارند، AI باید بداند چطور resolve کند.
مثلاً برای soil_moisture:
- اگر چند سنسور همعمق و همزون باشند → average
- اگر depth فرق دارد → shallow و deep را جدا نگه دار
- اگر یکی unhealthy باشد → ignore
- اگر یکی stale باشد → وزن کمتر بگیرد یا حذف شود
بنابراین برای هر metric این چیزها مهم میشوند:
recorded_atdepth_cmzonesensor_healthpriorityconfidence
الان average ساده خوب است برای شروع، ولی برای طراحی نهایی کافی نیست.
6) schema mapping را از business logic جدا کن
Backend و AI نباید به aliasهای vendor-specific وابسته بمانند.
مثلاً:
moisture_percentsoilMoisturemoisturesoil_moisture
همه باید به یک metric استاندارد map شوند:
soil_moisture
بهترین محل این mapping
به نظر من mapping باید در یک لایه canonical تعریف شود:
- در
SensorCatalog - یا در AI داخل
SensorParameter.metadata
مثلاً:
{
"code": "soil_moisture",
"metadata": {
"aliases": ["moisture_percent", "soilMoisture", "moisture"],
"unit": "%",
"valid_range": [0, 100]
}
}
پیشنهاد عملی برای Backend
Backend چه چیزی نگه دارد؟
مدلهای اصلی
SensorCatalog= تعریف نوع سنسورFarmSensor= دستگاه نصبشده روی مزرعهSensorExternalRequestLog= raw ingress log
مسئولیتها
- ثبت sensor inventory
- validate کردن physical device
- ثبت raw payload برای audit
- attach کردن payload به farm درست
- forward کردن payload به AI
چیزی که Backend نباید owner آن باشد
- منطق aggregation نهایی برای recommendation
- conflict resolution تخصصی برای سنسورهای متعدد
- semantic interpretation نهایی برای AI outputs
پیشنهاد عملی برای AI
AI چه چیزی نگه دارد؟
SensorData
برای هر farm_uuid:
sensor_payloadبر اساس device instanceplantsirrigation_methodcenter_locationweather_forecast
SensorParameter
برای تعریف metricهای استاندارد:
sensor_keycodename_faunitdata_typemetadata
ولی پیشنهاد میکنم metadata را برای این موارد غنیتر کنی:
aliasesvalid_rangeaggregation_strategysemantic_grouprecommended_for
ساختار پیشنهادی payload بین Backend و AI
بهجای فرستادن فقط این:
{
"sensor-7-1": {
"soil_moisture": 45.2
}
}
بهتر است به این سمت بروی:
{
"device:22222222-2222-2222-2222-222222222222": {
"sensor_key": "sensor-7-1",
"sensor_type": "soil_probe",
"recorded_at": "2026-05-02T10:15:00Z",
"metrics": {
"soil_moisture": 45.2,
"soil_temperature": 22.5
},
"metadata": {
"depth_cm": 20,
"zone": "zone-a"
}
}
}
اگر فعلاً نمیخواهی API را بشکنی، حداقل این migration path را برو:
- فعلاً
sensor_payloadفعلی را نگه دار - اجازه بده علاوه بر
sensor_key،physical_device_uuidهم به AI برسد - در AI key داخلی را با device uuid بساز
- بعداً schema را کامل migrate کن
الگوی تصمیمگیری برای چند سنسور
برای AI پیشنهاد میکنم سه خروجی داشته باشی:
1) raw_sensor_payload
همه دادههای هر device بدون از دست رفتن context
2) resolved_metrics
مثلاً:
{
"soil_moisture": 23.2,
"soil_temperature": 18.5
}
3) metric_sources
مثلاً:
{
"soil_moisture": {
"strategy": "weighted_average",
"sensor_keys": ["device:a", "device:b"],
"depths": [20, 40],
"conflict": true
}
}
این ساختار برای explainability خیلی مهم است.
چیزی که من پیشنهاد میکنم همین الان تغییر بدهی
تغییرات سریع و پرارزش
در Backend
- به
FarmSensorاین فیلدها را اضافه کن:metadatainstallation_zonedepth_cmlast_seen_atstatus
در AI
sensor_payloadرا بهسمت instance-based key ببرSensorParameter.metadataرا برای alias و aggregation strategy غنی کن- resolver فعلی را از
average سادهبه strategy-based resolver ارتقا بده
در API بین Backend و AI
- همراه payload این اطلاعات را هم بفرست:
physical_device_uuidsensor_catalog_uuidsensor_typerecorded_atdepth_cmیاzone
پیشنهاد naming
برای شفافیت بیشتر:
SensorCatalog= نوع سنسورFarmSensor= سنسور نصبشدهSensorExternalRequestLog= raw ingest logSensorData= farm sensor context
اگر بعداً مدل event اضافه کردی:
SensorReadingEvent= reading normalized per device
تصمیم نهایی من
اگر بخواهم خیلی خلاصه بگویم:
- Backend باید registry, ingestion, audit را handle کند
- AI باید normalization, aggregation, context-building, recommendation input را handle کند
- key اصلی داده سنسور باید sensor instance باشد، نه فقط
sensor_key - raw sensor data و resolved farm metrics باید از هم جدا باشند
نتیجه یکخطی
برای سنسورهای انعطافپذیر و چندتایی، Backend را بهعنوان لایه ثبت دستگاه و ورود raw data نگه دار و AI را بهعنوان لایه استانداردسازی و تجمیع metricها؛ و مهمتر از همه، دادهها را بر اساس device instance مدل کن نه فقط نوع سنسور.