Files
Ai/docs/farm_location_data_relationships.md
T
2026-05-11 15:31:10 +03:30

29 KiB

ارتباط farm_data، location_data و فیلدهای وابسته

این سند ساختار فعلی داده‌ها در پروژه را توضیح می‌دهد و هم‌زمان دو قاعده کسب‌وکاری مورد تایید را به‌عنوان مبنای توسعه ثبت می‌کند:

  1. برای محاسبه‌های عمومی هوش مصنوعی مثل RAG و crop_simulation باید از داده‌های تجمیع‌شده کل بلوک‌های بزرگِ تعریف‌شده توسط کشاورز استفاده شود.
  2. اگر برای یک مزرعه هیچ بلاکی تعریف نشده باشد، حالت پیش‌فرض باید شامل 1 بلوک بزرگ و 1 بلوک کوچک‌تر داخل همان بلوک بزرگ باشد.

این سند بر اساس ساختار فعلی کد در farm_data/, location_data/, weather/, rag/, crop_simulation/, irrigation/ و plant/ نوشته شده است.


1) نقش هر app در معماری داده

farm_data

این app رکورد canonical مزرعه برای مصرف لایه AI را نگه می‌دارد. مهم‌ترین رکورد آن SensorData است.

وظیفه‌های اصلی:

  • نگه‌داری شناسه مزرعه (farm_uuid)
  • اتصال مزرعه به SoilLocation
  • نگه‌داری payload سنسورها
  • نگه‌داری snapshot گیاه‌ها برای مصرف AI
  • اتصال به روش آبیاری و آب‌وهوا
  • ساخت خروجی تجمیعی مزرعه با get_farm_details()

location_data

این app مدل مکانی مزرعه و ساختار بلاک‌ها را نگه می‌دارد.

وظیفه‌های اصلی:

  • نگه‌داری مرکز هندسی مزرعه (SoilLocation)
  • نگه‌داری مرز کل مزرعه (farm_boundary)
  • نگه‌داری بلاک‌های اصلی کشاورز (block_layout.blocks)
  • نگه‌داری subdivision هر بلاک (BlockSubdivision)
  • نگه‌داری grid سلول‌ها و داده‌های سنجش‌ازدور
  • ساخت snapshotهای بلاکی و تجمیعی برای مصرف downstream

weather

پیش‌بینی آب‌وهوا را برای هر SoilLocation نگه می‌دارد. مزرعه از طریق center_location به forecast متصل می‌شود.

plant

مدل اصلی گیاه‌ها را نگه می‌دارد، اما برای لایه AI در farm_data یک read-model به نام PlantCatalogSnapshot ساخته شده است.

irrigation

جدول مرجع روش‌های آبیاری را نگه می‌دارد و farm_data.SensorData به یکی از آن‌ها متصل می‌شود.

rag و crop_simulation

این دو app مصرف‌کننده داده‌اند، نه مالک اصلی داده. یعنی داده اصلی را از farm_data, location_data, weather, plant و snapshotهای تجمیعی می‌گیرند.


2) موجودیت‌های اصلی و ارتباط بین آن‌ها

نمای کلی:

Farm (business id = farm_uuid)
   |
   v
farm_data.SensorData
   |-- FK --> location_data.SoilLocation
   |-- FK --> weather.WeatherForecast (optional cached/latest link)
   |-- FK --> irrigation.IrrigationMethod (optional)
   |-- JSON --> sensor_payload
   |-- M2M legacy --> plant.Plant
   |-- 1:N canonical --> farm_data.FarmPlantAssignment --> farm_data.PlantCatalogSnapshot

location_data.SoilLocation
   |-- JSON --> farm_boundary
   |-- int  --> input_block_count
   |-- JSON --> block_layout
   |-- 1:N --> BlockSubdivision
   |-- 1:N --> RemoteSensingRun
   |-- 1:N --> AnalysisGridCell
   |-- 1:N --> WeatherForecast
   |-- 1:N --> NdviObservation

BlockSubdivision
   |-- belongs to --> SoilLocation
   |-- identifies --> one main block (block_code)
   |-- stores --> source_boundary / centroid_points / subdivision_summary

RemoteSensingRun
   |-- belongs to --> SoilLocation
   |-- scoped by --> block_code
   |-- produces --> AnalysisGridObservation + RemoteSensingSubdivisionResult

RemoteSensingSubdivisionResult
   |-- belongs to --> RemoteSensingRun
   |-- scoped by --> block_code
   |-- produces --> RemoteSensingClusterBlock + RemoteSensingClusterAssignment

3) تعریف دقیق موجودیت‌ها

3.1) farm_data.SensorData

این مدل در عمل رکورد اصلی مزرعه برای مصرف AI است.

فیلدهای مهم:

  • farm_uuid

    • شناسه یکتای مزرعه
    • primary key
    • شناسه business-level بین appها
  • center_location

    • ForeignKey به location_data.SoilLocation
    • هر مزرعه دقیقاً به یک location مرکزی وصل است
    • نام legacy آن در بعضی جاها هنوز به‌صورت location دیده می‌شود، ولی canonical همان center_location است
  • weather_forecast

    • ForeignKey اختیاری به weather.WeatherForecast
    • آخرین forecast مرتبط با location را cache می‌کند
    • اگر خالی باشد، سرویس‌ها معمولاً از روی center_location.weather_forecasts آخرین رکورد را پیدا می‌کنند
  • sensor_payload

    • JSONField
    • ساختار چندسنسوری دارد
    • نمونه:
{
  "sensor-7-1": {
    "soil_moisture": 22.4,
    "soil_temperature": 18.1,
    "nitrogen": 31.0
  },
  "leaf-sensor": {
    "leaf_wetness": 11.0,
    "leaf_temperature": 19.3
  }
}
  • plants

    • relation قدیمی به plant.Plant
    • برای سازگاری عقب‌رو نگه داشته شده
    • canonical برای AI نیست
  • irrigation_method

    • ForeignKey اختیاری به irrigation.IrrigationMethod
  • created_at, updated_at

    • زمان ساخت و آخرین به‌روزرسانی رکورد مزرعه

نکته مهم:

  • SensorData مالک geometry مزرعه نیست.
  • geometry و بلاک‌ها در location_data نگه‌داری می‌شوند.
  • SensorData فقط به SoilLocation وصل می‌شود.

3.2) farm_data.PlantCatalogSnapshot

این مدل snapshot خواندنی از کاتالوگ گیاه Backend است تا سرویس‌های AI مستقیم به app اصلی گیاه وابسته نباشند.

فیلدهای مهم:

  • backend_plant_id
  • name
  • slug
  • icon
  • description
  • metadata
  • health_profile
  • irrigation_profile
  • growth_profile
  • growth_stage, growth_stages
  • is_active
  • source_updated_at

این مدل source of truth اصلی گیاه در کل سیستم نیست، ولی source of truth لایه AI برای گیاهِ sync‌شده است.


3.3) farm_data.FarmPlantAssignment

رابط canonical بین مزرعه و snapshot گیاه است.

فیلدهای مهم:

  • farm -> SensorData
  • plant -> PlantCatalogSnapshot
  • position
  • stage
  • metadata

کاربرد:

  • تعیین ترتیب گیاه‌های مزرعه
  • تعیین stage اختصاصی برای گیاه در همان مزرعه
  • حذف وابستگی مستقیم AI به SensorData.plants

3.4) farm_data.SensorParameter

تعریف metadata هر پارامتر سنسوری است.

فیلدهای مهم:

  • sensor_key
  • code
  • name_fa
  • unit
  • data_type
  • metadata

کاربرد:

  • ساخت schema داینامیک برای sensor_payload
  • ثبت سنسورهای جدید بدون migration

3.5) location_data.SoilLocation

این مدل نقطه مرکزی و ساختار فضایی مزرعه را نگه می‌دارد.

فیلدهای مهم:

  • latitude

  • longitude

    • مرکز هندسی مزرعه
    • روی این دو فیلد constraint یکتایی وجود دارد
  • task_id

    • شناسه taskهای async
  • farm_boundary

    • مرز کل مزرعه
    • معمولاً به شکل GeoJSON polygon ذخیره می‌شود
  • input_block_count

    • تعداد بلاک‌های اصلی تعریف‌شده توسط کشاورز
  • block_layout

    • ساختار کامل بلاک‌های اصلی و زیر‌بلاک‌های داخلی
    • مهم‌ترین فیلد spatial-read-model برای AI
  • created_at, updated_at

نکته مهم:

  • SoilLocation خود مزرعه نیست.
  • SoilLocation نمای مکانی مزرعه است.
  • مزرعه business-level با farm_uuid در SensorData شناسایی می‌شود.

3.6) location_data.BlockSubdivision

این مدل subdivision یک بلاک اصلی را نگه می‌دارد.

فیلدهای مهم:

  • soil_location
  • block_code
  • source_boundary
  • chunk_size_sqm
  • grid_points
  • centroid_points
  • grid_point_count
  • centroid_count
  • status
  • metadata
  • elbow_plot

تفسیر:

  • هر رکورد BlockSubdivision به یک main block تعلق دارد.
  • block_code همان شناسه بلاک اصلی کشاورز است.
  • centroid_points معمولاً نماینده زیر‌بلاک‌های داخلی است.

3.7) location_data.RemoteSensingRun

هر run سنجش‌ازدور برای یک location و معمولاً برای یک block_code اجرا می‌شود.

فیلدهای مهم:

  • soil_location
  • block_subdivision
  • block_code
  • provider
  • chunk_size_sqm
  • temporal_start
  • temporal_end
  • status
  • metadata
  • error_message

اگر block_code خالی باشد، run در سطح کل farm/location تفسیر می‌شود. اگر block_code مقدار داشته باشد، run مربوط به همان بلاک اصلی است.


3.8) location_data.AnalysisGridCell

سلول‌های شبکه تحلیلی برای سنجش‌ازدور هستند.

فیلدهای مهم:

  • soil_location
  • block_subdivision
  • block_code
  • cell_code
  • chunk_size_sqm
  • geometry
  • centroid_lat
  • centroid_lon

این‌ها لایه پایین‌تر از main block هستند و برای محاسبات remote sensing استفاده می‌شوند.


3.9) location_data.AnalysisGridObservation

خروجی متریک‌های سنجش‌ازدور برای هر cell در یک بازه زمانی است.

فیلدهای مهم:

  • cell
  • run
  • temporal_start
  • temporal_end
  • ndvi
  • ndwi
  • soil_vv
  • soil_vv_db
  • dem_m
  • slope_deg
  • metadata

این داده‌ها raw یا نیمه‌تجمیع‌شده‌اند و هنوز در سطح مزرعه نیستند.


3.10) location_data.RemoteSensingSubdivisionResult

نتیجه خوشه‌بندی داده‌محور برای یک run و یک بلاک است.

فیلدهای مهم:

  • run
  • soil_location
  • block_subdivision
  • block_code
  • chunk_size_sqm
  • cluster_count
  • selected_features
  • metadata

3.11) location_data.RemoteSensingClusterBlock

این مدل زیر‌بلاک‌های KMeans/cluster-based را نگه می‌دارد.

فیلدهای مهم:

  • uuid
  • result
  • soil_location
  • block_subdivision
  • block_code
  • sub_block_code
  • cluster_label
  • centroid_lat
  • centroid_lon
  • geometry
  • cell_count
  • cell_codes
  • metadata

نکته مهم:

  • این زیر‌بلاک‌ها با main block فرق دارند.
  • block_code = بلاک اصلی والد
  • sub_block_code = زیر‌بلاک داخلی ساخته‌شده با خوشه‌بندی

3.12) weather.WeatherForecast

پیش‌بینی هواشناسی برای یک SoilLocation است.

فیلدهای مهم:

  • location
  • forecast_date
  • temperature_min
  • temperature_max
  • temperature_mean
  • precipitation
  • precipitation_probability
  • humidity_mean
  • wind_speed_max
  • et0
  • weather_code
  • fetched_at

نکته:

  • آب‌وهوا به location وصل است، نه مستقیم به farm_uuid.
  • SensorData.weather_forecast فقط shortcut/cache است.

3.13) irrigation.IrrigationMethod

مدل مرجع روش آبیاری است.

فیلدهای مهم:

  • name
  • category
  • description
  • water_efficiency_percent
  • water_pressure_required
  • flow_rate
  • coverage_area
  • soil_type
  • climate_suitability

هر مزرعه می‌تواند صفر یا یک روش آبیاری انتخاب‌شده داشته باشد.


4) منبع اصلی هر نوع داده

نوع داده مالک اصلی فیلد/مدل canonical توضیح
شناسه مزرعه farm_data SensorData.farm_uuid شناسه business-level
مرکز مکانی مزرعه location_data SoilLocation.latitude/longitude centroid هندسی
مرز کل مزرعه location_data SoilLocation.farm_boundary شکل کل زمین
تعداد بلاک‌های اصلی location_data SoilLocation.input_block_count تعداد بلاک‌های کشاورز
ساختار بلاک‌ها location_data SoilLocation.block_layout بلاک‌های اصلی + sub-block metadata
تعریف subdivision هر بلاک location_data BlockSubdivision state و مرز هر بلاک
داده سنسور farm_data SensorData.sensor_payload source مستقیم از مزرعه/سنسور
schema پارامترهای سنسور farm_data SensorParameter metadata فیلدهای sensor_payload
گیاه‌های مزرعه farm_data FarmPlantAssignment canonical برای AI
catalog گیاه farm_data PlantCatalogSnapshot snapshot sync شده
forecast هوا weather WeatherForecast در سطح location
داده سنجش‌ازدور سلولی location_data AnalysisGridObservation خام/نیمه‌خام
تجمیع بلاک اصلی location_data snapshotهای satellite_snapshot.py برای AI
روش آبیاری irrigation IrrigationMethod جدول مرجع

5) دو سطح بلاک که نباید با هم قاطی شوند

در این پروژه دو سطح جدا داریم:

سطح اول: main block

این همان بلاک بزرگی است که کشاورز تعریف می‌کند.

محل نگه‌داری:

  • SoilLocation.block_layout["blocks"]
  • BlockSubdivision.block_code
  • RemoteSensingRun.block_code

مثال:

  • block-1
  • north-field
  • greenhouse-a

سطح دوم: sub block

این زیر‌بلاک داخلی است که یا:

  • از subdivision اولیه ساخته می‌شود
  • یا از خوشه‌بندی داده‌محور remote sensing/KMeans ساخته می‌شود

محل نگه‌داری:

  • BlockSubdivision.centroid_points
  • block_layout["blocks"][i]["sub_blocks"]
  • RemoteSensingClusterBlock
  • satellite_snapshot["satellite_sub_blocks"]
  • satellite_snapshot["sensor_sub_blocks"]

مثال:

  • sub-block-1
  • cluster-0
  • cluster-1

قانون مهم:

  • main block سطح تصمیم‌گیری کشاورز است.
  • sub block سطح تحلیل داخلی سیستم است.
  • برای AI عمومی باید جمع‌بندی روی main blockها انجام شود، نه این‌که مستقیماً یک sub block به‌عنوان نماینده کل مزرعه در نظر گرفته شود.

6) ساختار block_layout

SoilLocation.block_layout مهم‌ترین read-model فضایی برای کل سیستم است.

شکل عمومی:

{
  "input_block_count": 1,
  "default_full_farm": true,
  "algorithm_status": "pending",
  "blocks": [
    {
      "block_code": "block-1",
      "order": 1,
      "source": "default",
      "boundary": {},
      "needs_subdivision": null,
      "sub_blocks": []
    }
  ]
}

کلیدهای مهم:

  • input_block_count

    • تعداد بلاک‌های اصلی کشاورز
  • default_full_farm

    • اگر فقط یک بلاک اصلی وجود داشته باشد معمولاً true است
  • algorithm_status

    • وضعیت محاسبات بعدی روی layout
    • معمولاً pending یا completed
  • blocks

    • لیست بلاک‌های اصلی

هر آیتم blocks:

  • block_code

    • شناسه یکتای بلاک اصلی
  • order

    • ترتیب نمایش/تحلیل
  • source

    • معمولاً input یا default
  • boundary

    • مرز همان بلاک اصلی
  • needs_subdivision

    • آیا این بلاک نیاز به subdivision داخلی دارد
  • sub_blocks

    • لیست زیر‌بلاک‌های داخلی

در بعضی مرحله‌ها این layout با فیلدهای تکمیلی enrich می‌شود:

  • subdivision_summary
  • analysis_grid_summary
  • aggregated_metrics

7) جریان ساخت و به‌روزرسانی داده

7.1) وقتی POST /api/farm-data/ صدا زده می‌شود

این endpoint مزرعه را از دید AI upsert می‌کند.

جریان:

  1. farm_uuid و farm_boundary دریافت می‌شود.
  2. در resolve_center_location_from_boundary() centroid مزرعه محاسبه می‌شود.
  3. یک SoilLocation بر اساس centroid ساخته یا پیدا می‌شود.
  4. input_block_count و block_layout اولیه تنظیم می‌شوند.
  5. اگر ایجاد جدید باشد و فقط یک بلاک وجود داشته باشد، برای block-1 یک subdivision اولیه هم می‌تواند ساخته شود.
  6. forecast آب‌وهوا از روی location resolve می‌شود.
  7. رکورد SensorData ساخته یا آپدیت می‌شود.
  8. payload سنسورها merge می‌شود.
  9. plant assignmentها و irrigation method در صورت ارسال sync می‌شوند.

نکته:

  • این endpoint بیشتر مزرعه را به SoilLocation وصل می‌کند.
  • تعریف دقیق مرز هر main block معمولاً از مسیر location_data می‌آید، نه از farm_data.

7.2) وقتی POST /api/location-data/ صدا زده می‌شود

این endpoint ساختار مزرعه از دید spatial را ذخیره می‌کند.

جریان:

  1. lat, lon, farm_boundary, blocks دریافت می‌شود.
  2. SoilLocation بر اساس همان lat/lon ذخیره یا پیدا می‌شود.
  3. input_block_count و block_layout با لیست blocks به‌روزرسانی می‌شوند.
  4. _sync_defined_blocks() برای هر main block یک BlockSubdivision با status="defined" می‌سازد یا به‌روزرسانی می‌کند.
  5. اگر بلاکی حذف شده باشد، subdivision و state تحلیل قبلی آن پاک می‌شود.
  6. اگر boundary بلاکی تغییر کند، state تحلیل سنجش‌ازدور آن invalidate می‌شود.

پس:

  • location_data مالک تعریف بلاک‌های اصلی است.
  • farm_data مالک رکورد مزرعه برای AI است.

7.3) وقتی get_farm_details() ساخته می‌شود

این تابع خروجی canonical مزرعه را برای appهای دیگر تولید می‌کند.

خروجی شامل این بخش‌هاست:

  • center_location
  • weather
  • sensor_payload
  • sensor_schema
  • soil
  • plant_ids
  • plants
  • plant_assignments
  • irrigation_method
  • created_at, updated_at

بخش soil از ادغام این دو منبع ساخته می‌شود:

  • snapshotهای سنجش‌ازدور
  • sensor_payload

قاعده فعلی merge:

  • اگر برای یک metric داده سنسور وجود داشته باشد، روی داده remote sensing override می‌شود.
  • اگر چند سنسور مقدار متعارض بدهند:
    • برای داده عددی average گرفته می‌شود
    • برای داده غیرعددی distinct values برمی‌گردد

8) snapshotهای مکانی و معنای آن‌ها

در location_data/satellite_snapshot.py چند نوع snapshot مهم ساخته می‌شود:

build_location_satellite_snapshot(location, block_code="")

یک snapshot برای یک scope خاص می‌سازد:

  • اگر block_code خالی باشد: snapshot عمومی location/farm
  • اگر block_code پر باشد: snapshot همان main block

build_location_block_satellite_snapshots(location)

برای همه main blockهای ثبت‌شده snapshot می‌سازد.

خروجی هر بلاک شامل این‌هاست:

  • resolved_metrics
  • metric_sources
  • satellite_metrics
  • sensor_metrics
  • sensor_sub_blocks
  • satellite_sub_blocks
  • sub_block_count

build_farmer_block_aggregated_snapshot(location)

خروجی تجمیعی سطح مزرعه بر اساس همه main blockهای کشاورز است.

این مهم‌ترین تابع برای قانون کسب‌وکاری تو است، چون:

  • اگر چند main block وجود داشته باشد، میانگین آن‌ها را در سطح farmer-block می‌سازد
  • aggregation_strategy آن farmer_block_mean است
  • برای AI عمومی از نظر مفهومی این همان سطح درست مصرف داده است

9) قانون canonical برای محاسبه‌های عمومی AI

برای سرویس‌های عمومی هوش مصنوعی مثل:

  • RAG
  • crop_simulation
  • fertilization
  • irrigation
  • farm_alerts
  • هر سرویسی که قرار است از کل وضعیت مزرعه حرف بزند

باید سطح داده canonical این باشد:

سطح مجاز

  • کل مزرعه بر اساس تجمیع main blockهای کشاورز

تابع پیشنهادی canonical

  • build_farmer_block_aggregated_snapshot(location, sensor_payload=...)

دلیل

  • این تابع داده‌ها را از سطح main block بالا می‌آورد
  • اگر مزرعه چند بلاک اصلی داشته باشد، یک بلاک یا یک sub-block به اشتباه نماینده کل مزرعه نمی‌شود
  • با خواسته کسب‌وکاری تو هم‌راستا است

سطحی که نباید مبنای AI عمومی باشد

  • یک sub_block تکی
  • یک cluster-0 یا cluster-1 به‌تنهایی
  • snapshot خام location بدون درنظرگرفتن بلاک‌های اصلی کشاورز، مگر فقط به‌عنوان fallback

10) وضعیت پیش‌فرض وقتی بلاک تعریف نشده است

قاعده مورد تایید:

  • اگر کشاورز هنوز بلاک‌ها را تعریف نکرده باشد:
    • یک main block پیش‌فرض وجود دارد
    • داخل آن هم یک sub block پیش‌فرض وجود دارد

نمایش منطقی مورد انتظار

{
  "input_block_count": 1,
  "default_full_farm": true,
  "algorithm_status": "pending",
  "blocks": [
    {
      "block_code": "block-1",
      "order": 1,
      "source": "default",
      "boundary": {},
      "needs_subdivision": false,
      "sub_blocks": [
        {
          "sub_block_code": "sub-block-1"
        }
      ]
    }
  ]
}

تفسیر این قانون

  • block-1 نماینده کل مزرعه است
  • sub-block-1 حداقل واحد داخلی برای این‌که downstreamها همیشه ساختار یکنواخت ببینند

نکته درباره وضعیت فعلی کد

کد فعلی به‌صورت پیش‌فرض 1 main block را به‌خوبی می‌سازد، اما وجود 1 sub-block پیش‌فرض باید به‌عنوان قانون توسعه حفظ و در همه entry pointها یکدست شود.


11) ارتباط این داده‌ها با appهای دیگر

11.1) rag

rag معمولاً context مزرعه را از farm_data می‌گیرد.

نقاط مهم:

  • rag.chat.build_rag_context() از get_farm_details() استفاده می‌کند
  • rag.user_data.build_user_soil_text() علاوه بر داده‌های مزرعه، از:
    • build_farmer_block_aggregated_snapshot()
    • build_location_block_satellite_snapshots() استفاده می‌کند

نتیجه:

  • برای RAG عمومی، سطح درست context باید تجمیع main blockها باشد
  • جزئیات بلاکی و زیر‌بلاکی فقط برای explanation تکمیلی مناسب‌اند

11.2) crop_simulation

crop_simulation از این داده‌ها استفاده می‌کند:

  • SensorData
  • center_location
  • forecastهای هوا
  • snapshotهای خاک/سنجش‌ازدور
  • plant profile
  • irrigation method

قاعده مورد انتظار:

  • اگر خروجی برای کل مزرعه است، ورودی خاک/سنسور باید از تجمیع main blockهای کشاورز بیاید
  • نه از یک location snapshot ساده یا یک sub-block خاص

11.3) weather

سرویس‌های هواشناسی به SensorData.center_location متکی هستند و forecast را از WeatherForecastهای همان location می‌خوانند.

11.4) soile

تحلیل‌های خاک و anomaly detection از load_farm_context() و snapshotهای location استفاده می‌کنند. برای use-caseهای farm-wide، باید همان rule تجمیع main blockها رعایت شود.

11.5) farm_alerts

این app از load_farm_context() و get_farm_details() استفاده می‌کند. بنابراین هر تغییری در canonical farm context مستقیماً روی alertها اثر می‌گذارد.


12) تفاوت farm_boundary با block boundary

این دو نباید با هم اشتباه شوند:

farm_boundary

  • مرز کل زمین
  • در SoilLocation.farm_boundary
  • فقط یکی برای هر location

blocks[i].boundary

  • مرز هر بلاک اصلی کشاورز
  • در SoilLocation.block_layout["blocks"]
  • به‌ازای هر main block یک boundary

نتیجه:

  • farm_boundary = outer shell کل مزرعه
  • block boundary = تقسیم داخلی همان مزرعه

13) تفاوت center_location با farm_uuid

farm_uuid

  • شناسه business-level مزرعه
  • در SensorData
  • چیزی است که APIهای AI بیشتر با آن کار می‌کنند

center_location

  • شناسه مکانی centroid-based
  • در SoilLocation
  • چیزی است که weather, remote sensing, block layout و geometry به آن وصل‌اند

یک farm_uuid به یک center_location وصل می‌شود، اما معنا و مسئولیتشان متفاوت است:

  • farm_uuid = هویت مزرعه
  • center_location = هویت مکانی مزرعه

14) فیلدهایی که downstreamها باید canonical از آن‌ها بخوانند

اگر سرویسی بخواهد داده مزرعه را بخواند، اولویت canonical این‌طور است:

هویت مزرعه

  • SensorData.farm_uuid

geometry و ساختار بلاک

  • SensorData.center_location
  • SensorData.center_location.farm_boundary
  • SensorData.center_location.block_layout

داده سنسور

  • SensorData.sensor_payload

schema سنسور

  • farm_data.SensorParameter

گیاه

  • FarmPlantAssignment + PlantCatalogSnapshot

آب‌وهوا

  • SensorData.weather_forecast اگر موجود بود
  • در غیر این صورت center_location.weather_forecasts

summary خاک/remote sensing برای کل مزرعه

  • build_farmer_block_aggregated_snapshot(...)

summary برای هر main block

  • build_location_block_satellite_snapshots(...)

summary برای زیر‌بلاک‌ها

  • satellite_sub_blocks و sensor_sub_blocks

15) نمونه خلاصه مفهومی برای یک مزرعه

farm_uuid = شناسه اصلی مزرعه
center_location = centroid و ساختار spatial مزرعه
farm_boundary = مرز کل زمین
block_layout = بلاک‌های اصلی تعریف‌شده توسط کشاورز
block_subdivisions = وضعیت subdivision هر بلاک اصلی
analysis_grid = سلول‌های داخلی برای سنجش‌ازدور
remote_sensing = متریک‌های سلولی و تجمیع‌شده
sensor_payload = سنسورهای واقعی نصب‌شده در مزرعه
plants = گیاه‌های sync شده برای AI
weather = forecastهای location
irrigation_method = روش آبیاری انتخاب‌شده
AI general context = farmer-block aggregated snapshot + sensor payload + weather + plant + irrigation

16) جمع‌بندی نهایی

اگر بخواهیم یک قانون ساده و پایدار برای کل سیستم تعریف کنیم:

  • farm_data مالک رکورد AI-facing مزرعه است.
  • location_data مالک geometry، بلاک‌ها، subdivision و remote sensing است.
  • weather مالک forecastهای location است.
  • plant و snapshotهای آن مالک context گیاهی مزرعه‌اند.
  • irrigation مالک روش آبیاری است.

و از نظر محاسبات عمومی AI:

  • سطح تصمیم‌گیری باید کل main blockهای کشاورز باشد.
  • sub_blockها فقط جزئیات داخلی و تحلیلی هستند.
  • اگر بلاکی تعریف نشده بود، مدل ذهنی و داده‌ای پیش‌فرض باید 1 main block + 1 sub-block داخلی باشد.