AI UPDATE
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_anomaly_detection_card(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
sensor = (context or {}).get("sensor")
|
||||
if sensor is None:
|
||||
return {"anomalies": []}
|
||||
|
||||
anomalies = []
|
||||
moisture = safe_number(sensor.soil_moisture, 0)
|
||||
if moisture < 45:
|
||||
anomalies.append(
|
||||
{
|
||||
"sensor": "رطوبت خاک",
|
||||
"value": f"{round(moisture)}%",
|
||||
"expected": "45-65%",
|
||||
"deviation": f"{round(moisture - 55)}%",
|
||||
"severity": "warning",
|
||||
}
|
||||
)
|
||||
|
||||
soil_ph = safe_number(sensor.soil_ph, 7)
|
||||
if soil_ph < 6 or soil_ph > 7:
|
||||
anomalies.append(
|
||||
{
|
||||
"sensor": "pH خاک",
|
||||
"value": f"{soil_ph:.1f}",
|
||||
"expected": "6.0-7.0",
|
||||
"deviation": f"{round(soil_ph - 6.5, 1)}",
|
||||
"severity": "error" if soil_ph < 5.5 or soil_ph > 7.5 else "warning",
|
||||
}
|
||||
)
|
||||
|
||||
return {"anomalies": anomalies}
|
||||
@@ -0,0 +1,50 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_economic_overview(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
sensor = (context or {}).get("sensor")
|
||||
forecasts = (context or {}).get("forecasts", [])
|
||||
if sensor is None:
|
||||
return {"economicData": [], "chartSeries": [], "chartCategories": []}
|
||||
|
||||
water_cost = round(sum(max(0, safe_number(forecast.et0, 0) * 20) for forecast in forecasts[:6]))
|
||||
fertilizer_need = round((safe_number(sensor.nitrogen, 0) + safe_number(sensor.phosphorus, 0) + safe_number(sensor.potassium, 0)) / 3)
|
||||
revenue = round(max(1000, water_cost * 4.5))
|
||||
|
||||
return {
|
||||
"economicData": [
|
||||
{
|
||||
"title": "هزینه آب",
|
||||
"value": f"€{water_cost}",
|
||||
"subtitle": "این ماه",
|
||||
"avatarIcon": "tabler-droplet",
|
||||
"avatarColor": "primary",
|
||||
},
|
||||
{
|
||||
"title": "صرفهجویی آب هوشمند",
|
||||
"value": f"€{round(water_cost * 0.18)}",
|
||||
"subtitle": "۱۸٪ صرفهجویی شده",
|
||||
"avatarIcon": "tabler-bulb",
|
||||
"avatarColor": "success",
|
||||
},
|
||||
{
|
||||
"title": "بازده سرمایه پلتفرم",
|
||||
"value": "127%",
|
||||
"subtitle": "نسبت به سال گذشته",
|
||||
"avatarIcon": "tabler-chart-line",
|
||||
"avatarColor": "info",
|
||||
},
|
||||
{
|
||||
"title": "پیشبینی درآمد",
|
||||
"value": f"€{round(revenue / 1000)}k",
|
||||
"subtitle": "این فصل",
|
||||
"avatarIcon": "tabler-currency-euro",
|
||||
"avatarColor": "success",
|
||||
},
|
||||
],
|
||||
"chartSeries": [
|
||||
{"name": "هزینه آب", "data": [max(1, round(water_cost / 6)) for _ in range(6)]},
|
||||
{"name": "کود", "data": [max(1, round(fertilizer_need / 6)) for _ in range(6)]},
|
||||
],
|
||||
"chartCategories": ["ژانویه", "فوریه", "مارس", "آوریل", "می", "ژوئن"],
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
def build_farm_alerts_timeline(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
ai_bundle = ai_bundle or {}
|
||||
return {"alerts": ai_bundle.get("timeline", [])}
|
||||
@@ -0,0 +1,41 @@
|
||||
from dashboard_data.card_utils import average, safe_number
|
||||
|
||||
|
||||
def build_farm_alerts_tracker(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
forecasts = context.get("forecasts", [])
|
||||
if sensor is None:
|
||||
return {"totalAlerts": 0, "radialBarValue": 0, "alertStats": []}
|
||||
|
||||
moisture = safe_number(sensor.soil_moisture, 0)
|
||||
humidity = average([forecast.humidity_mean for forecast in forecasts[:3]], default=0)
|
||||
frost_count = sum(1 for forecast in forecasts[:3] if safe_number(forecast.temperature_min, 10) <= 0)
|
||||
low_water_count = 2 if moisture < 45 else 0
|
||||
fungal_count = 1 if humidity > 70 and moisture > 60 else 0
|
||||
total = low_water_count + fungal_count + frost_count
|
||||
|
||||
return {
|
||||
"totalAlerts": total,
|
||||
"radialBarValue": min(100, total * 10),
|
||||
"alertStats": [
|
||||
{
|
||||
"title": "کمبود آب",
|
||||
"count": str(low_water_count),
|
||||
"avatarColor": "error",
|
||||
"avatarIcon": "tabler-droplet-half-2",
|
||||
},
|
||||
{
|
||||
"title": "ریسک قارچی",
|
||||
"count": str(fungal_count),
|
||||
"avatarColor": "warning",
|
||||
"avatarIcon": "tabler-mushroom",
|
||||
},
|
||||
{
|
||||
"title": "هشدار یخبندان",
|
||||
"count": str(frost_count),
|
||||
"avatarColor": "info",
|
||||
"avatarIcon": "tabler-snowflake",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
from dashboard_data.card_utils import average, safe_number
|
||||
|
||||
|
||||
def build_farm_overview_kpis(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
forecasts = context.get("forecasts", [])
|
||||
if sensor is None:
|
||||
return {"kpis": []}
|
||||
|
||||
moisture = safe_number(sensor.soil_moisture, 0)
|
||||
ph = safe_number(sensor.soil_ph, 7)
|
||||
ec = safe_number(sensor.electrical_conductivity, 0)
|
||||
humidity = average([forecast.humidity_mean for forecast in forecasts[:3]], default=45)
|
||||
health_score = max(0, min(100, round(100 - abs(65 - moisture) - (abs(6.8 - ph) * 10) - (ec * 5))))
|
||||
water_stress = max(0, min(100, round(35 - (moisture / 2))))
|
||||
disease_risk = max(0, min(100, round((humidity * 0.4) + (safe_number(sensor.soil_temperature, 0) * 0.6) - 20)))
|
||||
yield_prediction = round(max(5, (health_score / 2.1)), 1)
|
||||
|
||||
return {
|
||||
"kpis": [
|
||||
{
|
||||
"id": "farm_health_score",
|
||||
"title": "امتیاز سلامت مزرعه",
|
||||
"subtitle": "تحلیل هوشمند",
|
||||
"stats": f"{health_score}%",
|
||||
"avatarColor": "success" if health_score >= 70 else "warning",
|
||||
"avatarIcon": "tabler-heartbeat",
|
||||
"chipText": "خوب" if health_score >= 70 else "متوسط",
|
||||
"chipColor": "success" if health_score >= 70 else "warning",
|
||||
},
|
||||
{
|
||||
"id": "water_stress_index",
|
||||
"title": "شاخص تنش آبی",
|
||||
"subtitle": "فعلی",
|
||||
"stats": f"{water_stress}%",
|
||||
"avatarColor": "info",
|
||||
"avatarIcon": "tabler-droplet",
|
||||
"chipText": "پایین" if water_stress <= 20 else "متوسط",
|
||||
"chipColor": "success" if water_stress <= 20 else "warning",
|
||||
},
|
||||
{
|
||||
"id": "disease_risk",
|
||||
"title": "ریسک بیماری",
|
||||
"subtitle": "۷ روز اخیر",
|
||||
"stats": "پایین" if disease_risk < 30 else "متوسط",
|
||||
"avatarColor": "success" if disease_risk < 30 else "warning",
|
||||
"avatarIcon": "tabler-bug",
|
||||
"chipText": f"{disease_risk}%",
|
||||
"chipColor": "success" if disease_risk < 30 else "warning",
|
||||
},
|
||||
{
|
||||
"id": "avg_soil_moisture",
|
||||
"title": "میانگین رطوبت خاک",
|
||||
"subtitle": "کل مزرعه",
|
||||
"stats": f"{round(moisture)}%",
|
||||
"avatarColor": "primary",
|
||||
"avatarIcon": "tabler-plant-2",
|
||||
"chipText": "بهینه" if 45 <= moisture <= 75 else "نیازمند بررسی",
|
||||
"chipColor": "success" if 45 <= moisture <= 75 else "warning",
|
||||
},
|
||||
{
|
||||
"id": "yield_prediction",
|
||||
"title": "پیشبینی عملکرد",
|
||||
"subtitle": "این فصل",
|
||||
"stats": f"{yield_prediction} تن",
|
||||
"avatarColor": "secondary",
|
||||
"avatarIcon": "tabler-chart-bar",
|
||||
"chipText": f"+{max(0, health_score - 50)}%",
|
||||
"chipColor": "success",
|
||||
},
|
||||
{
|
||||
"id": "pest_risk",
|
||||
"title": "ریسک آفات",
|
||||
"subtitle": "پیشبینی هوشمند",
|
||||
"stats": f"{max(5, round(disease_risk * 0.7))}%",
|
||||
"avatarColor": "warning",
|
||||
"avatarIcon": "tabler-bug-off",
|
||||
"chipText": "تحت نظر",
|
||||
"chipColor": "warning",
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
from dashboard_data.card_utils import average, safe_number, weather_condition
|
||||
|
||||
|
||||
def build_farm_weather_card(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
forecasts = (context or {}).get("forecasts", [])
|
||||
if not forecasts:
|
||||
return {
|
||||
"condition": "نامشخص",
|
||||
"temperature": 0,
|
||||
"unit": "°C",
|
||||
"humidity": 0,
|
||||
"windSpeed": 0,
|
||||
"windUnit": "km/h",
|
||||
"chartData": {"labels": [], "series": [[]]},
|
||||
}
|
||||
|
||||
current_forecast = forecasts[0]
|
||||
labels = [str(forecast.forecast_date) for forecast in forecasts[:7]]
|
||||
series = [[round(safe_number(forecast.temperature_mean, 0)) for forecast in forecasts[:7]]]
|
||||
|
||||
return {
|
||||
"condition": weather_condition(current_forecast.weather_code),
|
||||
"temperature": round(safe_number(current_forecast.temperature_mean, current_forecast.temperature_max)),
|
||||
"unit": "°C",
|
||||
"humidity": round(average([current_forecast.humidity_mean], default=0)),
|
||||
"windSpeed": round(safe_number(current_forecast.wind_speed_max, 0)),
|
||||
"windUnit": "km/h",
|
||||
"chartData": {
|
||||
"labels": labels,
|
||||
"series": series,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
from datetime import date, timedelta
|
||||
|
||||
from dashboard_data.card_utils import average, safe_number
|
||||
|
||||
|
||||
def build_harvest_prediction_card(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
forecasts = context.get("forecasts", [])
|
||||
plants = context.get("plants", [])
|
||||
|
||||
avg_temp = average([forecast.temperature_mean for forecast in forecasts], default=24)
|
||||
moisture_factor = safe_number(getattr(context.get("sensor"), "soil_moisture", None), 50)
|
||||
days_until = max(10, int(90 - avg_temp - (moisture_factor / 5)))
|
||||
target_date = date.today() + timedelta(days=days_until)
|
||||
window_start = target_date - timedelta(days=3)
|
||||
window_end = target_date + timedelta(days=3)
|
||||
plant_name = plants[0].name if plants else "محصول"
|
||||
|
||||
return {
|
||||
"date": str(target_date),
|
||||
"dateFormatted": f"{target_date.day} {target_date.strftime('%B')} {target_date.year}",
|
||||
"daysUntil": days_until,
|
||||
"description": f"بر اساس دمای فعلی، رطوبت خاک و اطلاعات {plant_name}. بازه بهینه برداشت محاسبه شده است.",
|
||||
"optimalWindowStart": str(window_start),
|
||||
"optimalWindowEnd": str(window_end),
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_ndvi_health_card(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
if sensor is None:
|
||||
return {"ndviIndex": 0, "healthData": []}
|
||||
|
||||
nitrogen = safe_number(sensor.nitrogen, 0)
|
||||
moisture = safe_number(sensor.soil_moisture, 0)
|
||||
ndvi = round(min(0.95, max(0.1, ((nitrogen / 100) * 0.4) + ((moisture / 100) * 0.6))), 2)
|
||||
|
||||
return {
|
||||
"ndviIndex": ndvi,
|
||||
"healthData": [
|
||||
{
|
||||
"title": "تنش نیتروژن",
|
||||
"value": "پایین" if nitrogen >= 30 else "بالا",
|
||||
"color": "success" if nitrogen >= 30 else "warning",
|
||||
"icon": "tabler-leaf",
|
||||
},
|
||||
{
|
||||
"title": "سلامت محصول",
|
||||
"value": "خوب" if ndvi >= 0.65 else "متوسط",
|
||||
"color": "success" if ndvi >= 0.65 else "warning",
|
||||
"icon": "tabler-plant",
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
def build_recommendations_list(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
ai_bundle = ai_bundle or {}
|
||||
return {"recommendations": ai_bundle.get("recommendations", [])}
|
||||
@@ -0,0 +1,35 @@
|
||||
from datetime import date, timedelta
|
||||
|
||||
from dashboard_data.card_utils import PERSIAN_WEEKDAYS, safe_number
|
||||
|
||||
|
||||
def build_sensor_comparison_chart(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
history = (context or {}).get("history", [])
|
||||
current_sensor = (context or {}).get("sensor")
|
||||
current_value = round(safe_number(getattr(current_sensor, "soil_moisture", None), 0))
|
||||
|
||||
recent = list(reversed(history[:7]))
|
||||
previous = list(reversed(history[7:14]))
|
||||
this_week = [round(safe_number(item.soil_moisture, current_value)) for item in recent]
|
||||
last_week = [round(safe_number(item.soil_moisture, current_value - 5)) for item in previous]
|
||||
|
||||
while len(this_week) < 7:
|
||||
this_week.append(current_value)
|
||||
while len(last_week) < 7:
|
||||
last_week.append(max(0, current_value - 5))
|
||||
|
||||
categories = [PERSIAN_WEEKDAYS[(date.today() - timedelta(days=offset)).weekday()] for offset in range(6, -1, -1)]
|
||||
avg_this = sum(this_week) / len(this_week)
|
||||
avg_last = sum(last_week) / len(last_week)
|
||||
delta = round(((avg_this - avg_last) / avg_last) * 100) if avg_last else 0
|
||||
|
||||
return {
|
||||
"currentValue": current_value,
|
||||
"vsLastWeek": f"{'+' if delta >= 0 else ''}{delta}%",
|
||||
"vsLastWeekValue": delta,
|
||||
"categories": categories,
|
||||
"series": [
|
||||
{"name": "امروز", "data": this_week},
|
||||
{"name": "هفته قبل", "data": last_week},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def _to_score(value, lower, upper):
|
||||
if value is None:
|
||||
return 0
|
||||
if value <= lower:
|
||||
return 0
|
||||
if value >= upper:
|
||||
return 100
|
||||
return round(((value - lower) / (upper - lower)) * 100)
|
||||
|
||||
|
||||
def build_sensor_radar_chart(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
forecasts = context.get("forecasts", [])
|
||||
if sensor is None:
|
||||
return {"labels": [], "series": []}
|
||||
|
||||
current_weather = forecasts[0] if forecasts else None
|
||||
current = [
|
||||
_to_score(sensor.soil_temperature, 0, 40),
|
||||
_to_score(sensor.soil_moisture, 0, 100),
|
||||
_to_score(sensor.soil_ph, 0, 14),
|
||||
_to_score(sensor.electrical_conductivity, 0, 5),
|
||||
85,
|
||||
_to_score(current_weather.wind_speed_max if current_weather else 0, 0, 30),
|
||||
]
|
||||
|
||||
return {
|
||||
"labels": ["دما", "رطوبت", "pH", "هدایت الکتریکی", "نور", "باد"],
|
||||
"series": [
|
||||
{"name": "امروز", "data": current},
|
||||
{"name": "ایدهآل", "data": [80, 70, 75, 75, 90, 50]},
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
from dashboard_data.card_utils import compute_trend, latest_history_value, safe_number
|
||||
|
||||
|
||||
def build_sensor_values_list(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
history = context.get("history", [])
|
||||
forecasts = context.get("forecasts", [])
|
||||
if sensor is None:
|
||||
return {"sensors": []}
|
||||
|
||||
current_weather = forecasts[0] if forecasts else None
|
||||
|
||||
sensors = [
|
||||
{
|
||||
"title": f"{round(safe_number(current_weather.temperature_mean if current_weather else None, 0))}°C",
|
||||
"subtitle": "دمای هوا",
|
||||
**compute_trend(
|
||||
current_weather.temperature_mean if current_weather else 0,
|
||||
latest_history_value(history, "soil_temperature", 0),
|
||||
),
|
||||
"unit": "°C",
|
||||
},
|
||||
{
|
||||
"title": f"{round(safe_number(sensor.soil_temperature, 0))}°C",
|
||||
"subtitle": "دمای خاک",
|
||||
**compute_trend(sensor.soil_temperature, latest_history_value(history, "soil_temperature", 0)),
|
||||
"unit": "°C",
|
||||
},
|
||||
{
|
||||
"title": f"{round(safe_number(current_weather.humidity_mean if current_weather else None, 0))}%",
|
||||
"subtitle": "رطوبت هوا",
|
||||
**compute_trend(current_weather.humidity_mean if current_weather else 0, 0),
|
||||
"unit": "%",
|
||||
},
|
||||
{
|
||||
"title": f"{round(safe_number(sensor.soil_moisture, 0))}%",
|
||||
"subtitle": "رطوبت خاک (۱۰ سانتیمتر)",
|
||||
**compute_trend(sensor.soil_moisture, latest_history_value(history, "soil_moisture", 0)),
|
||||
"unit": "%",
|
||||
},
|
||||
{
|
||||
"title": f"{safe_number(sensor.soil_ph, 0):.1f}",
|
||||
"subtitle": "pH خاک",
|
||||
**compute_trend(sensor.soil_ph, latest_history_value(history, "soil_ph", 0)),
|
||||
"unit": "pH",
|
||||
},
|
||||
{
|
||||
"title": f"{safe_number(sensor.electrical_conductivity, 0):.1f}",
|
||||
"subtitle": "هدایت الکتریکی (dS/m)",
|
||||
**compute_trend(
|
||||
sensor.electrical_conductivity,
|
||||
latest_history_value(history, "electrical_conductivity", 0),
|
||||
),
|
||||
"unit": "dS/m",
|
||||
},
|
||||
{
|
||||
"title": "850",
|
||||
"subtitle": "شدت نور (لوکس)",
|
||||
"trendNumber": 0,
|
||||
"trend": "positive",
|
||||
"unit": "lux",
|
||||
},
|
||||
{
|
||||
"title": f"{round(safe_number(current_weather.wind_speed_max if current_weather else None, 0))}",
|
||||
"subtitle": "سرعت باد (کیلومتر/ساعت)",
|
||||
**compute_trend(current_weather.wind_speed_max if current_weather else 0, 0),
|
||||
"unit": "km/h",
|
||||
},
|
||||
]
|
||||
return {"sensors": sensors}
|
||||
@@ -0,0 +1,32 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_soil_moisture_heatmap(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
context = context or {}
|
||||
sensor = context.get("sensor")
|
||||
depths = context.get("depths", [])
|
||||
if sensor is None:
|
||||
return {"zones": [], "hours": [], "series": []}
|
||||
|
||||
hours = ["۶ ص", "۸ ص", "۱۰ ص", "۱۲ ظ", "۱۴ ع", "۱۶ ع", "۱۸ ع"]
|
||||
base_moisture = safe_number(sensor.soil_moisture, 0)
|
||||
series = []
|
||||
zones = []
|
||||
|
||||
if not depths:
|
||||
depths = [None, None]
|
||||
|
||||
for index, depth in enumerate(depths[:7], start=1):
|
||||
zones.append(f"زون {index}")
|
||||
depth_offset = 0 if depth is None else round(safe_number(getattr(depth, "wv0033", None), 0) / 10)
|
||||
data = []
|
||||
for hour_index, hour in enumerate(hours):
|
||||
value = max(0, min(100, round(base_moisture + depth_offset - abs(3 - hour_index) * 2)))
|
||||
data.append({"x": hour, "y": value})
|
||||
series.append({"name": f"زون {index}", "data": data})
|
||||
|
||||
return {
|
||||
"zones": zones,
|
||||
"hours": hours,
|
||||
"series": series,
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_water_need_prediction(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
forecasts = (context or {}).get("forecasts", [])
|
||||
daily_needs = []
|
||||
for forecast in forecasts[:7]:
|
||||
et0 = safe_number(forecast.et0, 4)
|
||||
rain = safe_number(forecast.precipitation, 0)
|
||||
need = max(0, round((et0 * 100) - (rain * 20)))
|
||||
daily_needs.append(need)
|
||||
|
||||
return {
|
||||
"totalNext7Days": sum(daily_needs),
|
||||
"unit": "m³",
|
||||
"categories": [f"روز {index}" for index in range(1, len(daily_needs) + 1)],
|
||||
"series": [{"name": "نیاز آبی", "data": daily_needs}],
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
from datetime import date
|
||||
|
||||
from dashboard_data.card_utils import safe_number
|
||||
|
||||
|
||||
def build_yield_prediction_chart(sensor_id: str, context: dict | None = None, ai_bundle: dict | None = None) -> dict:
|
||||
sensor = (context or {}).get("sensor")
|
||||
if sensor is None:
|
||||
return {"categories": [], "series": [], "summary": []}
|
||||
|
||||
base = max(10, round(safe_number(sensor.soil_moisture, 0) * 0.6))
|
||||
current_year = [base + offset for offset in [0, 2, 4, 6, 8, 10, 12, 11, 9, 7, 5, 4]]
|
||||
last_year = [value - 3 for value in current_year]
|
||||
harvest_month = "حدود " + str(date.today().month)
|
||||
|
||||
return {
|
||||
"categories": ["ژانویه", "فوریه", "مارس", "آوریل", "می", "ژوئن", "ژوئیه", "آگوست", "سپتامبر", "اکتبر", "نوامبر", "دسامبر"],
|
||||
"series": [
|
||||
{"name": "امسال", "data": current_year},
|
||||
{"name": "سال گذشته", "data": last_year},
|
||||
],
|
||||
"summary": [
|
||||
{
|
||||
"title": "عملکرد پیشبینیشده",
|
||||
"subtitle": "این فصل",
|
||||
"amount": f"{current_year[9]} تن",
|
||||
"avatarColor": "primary",
|
||||
"avatarIcon": "tabler-chart-bar",
|
||||
},
|
||||
{
|
||||
"title": "تاریخ برداشت",
|
||||
"subtitle": harvest_month,
|
||||
"amount": "+8%",
|
||||
"avatarColor": "success",
|
||||
"avatarIcon": "tabler-calendar",
|
||||
},
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user