tele_bot / alerts.py
PRC142004's picture
Upload 21 files
945d0f8 verified
"""
Professional Alert Decision Engine
===================================
Generates real-time alerts based on weather, pest, and water data
Follows climate-resilient agriculture best practices
"""
import logging
from datetime import datetime
from typing import List, Dict, Optional
logger = logging.getLogger("DecisionEngine")
# Alert severity constants
SEVERITY_CRITICAL = "CRITICAL"
SEVERITY_HIGH = "HIGH"
SEVERITY_MEDIUM = "MEDIUM"
SEVERITY_LOW = "LOW"
SEVERITY_INFO = "INFO"
def calculate_climate_resilience_score(w_intel: Dict, p_intel: Dict, water_intel: Dict, farmer: Dict) -> Dict:
"""Calculate comprehensive climate resilience index (0-100)"""
score_components = {}
# Weather Risk (30 points max)
curr = w_intel.get("current", {})
temp = curr.get("temp", 25)
wind = curr.get("wind", 0)
forecast = w_intel.get("forecast", [])
weather_score = 30
if temp > farmer.get("threshold_settings", {}).get("temp_high", 40):
weather_score -= 15
elif temp < farmer.get("threshold_settings", {}).get("temp_low", 5):
weather_score -= 10
if wind > farmer.get("threshold_settings", {}).get("wind_speed", 30):
weather_score -= 15
heavy_rain_days = len([d for d in forecast if "heavy" in d.get("description", "").lower()])
if heavy_rain_days > 2:
weather_score -= 5 * heavy_rain_days
score_components["weather_risk"] = max(0, weather_score)
# Pest Risk (30 points max)
pest_score = 30
for pest in p_intel.get("pest_prediction_table", []):
severity = pest.get("severity", "").upper()
if severity == "CRITICAL":
pest_score -= 15
elif severity == "HIGH":
pest_score -= 10
elif severity == "MEDIUM":
pest_score -= 5
score_components["pest_risk"] = max(0, pest_score)
# Water Management Risk (20 points max)
water_score = 20
irrigation_minutes = water_intel.get("irrigation_minutes", 0)
water_m3 = water_intel.get("water_m3_sqm", 0)
# Optimal range: 20-40 minutes
if irrigation_minutes < 20 or irrigation_minutes > 50:
water_score -= 10
score_components["water_risk"] = max(0, water_score)
# Resource Efficiency (20 points max)
efficiency_score = 20
rain_next_7days = len([d for d in forecast if "rain" in d.get("description", "").lower()])
# More rain = less irrigation needed = better efficiency
if rain_next_7days > 2:
efficiency_score = 20
elif irrigation_minutes > 40:
efficiency_score = 10
score_components["resource_efficiency"] = efficiency_score
total_score = sum([score_components["weather_risk"],
score_components["pest_risk"],
score_components["water_risk"],
score_components["resource_efficiency"]])
resilience_level = "🟒 GREEN" if total_score >= 75 else "🟑 YELLOW" if total_score >= 50 else "πŸ”΄ RED"
return {
"total_score": total_score,
"components": score_components,
"resilience_level": resilience_level,
"critical_factors": [k for k, v in score_components.items() if v < 15]
}
def get_alerts(w_intel: Dict, p_intel: Dict, water_intel: Dict, farmer: Dict) -> List[Dict]:
"""
Generate actionable alerts with severity levels
Returns list of professional farm alerts
"""
alerts = []
# Core Data Extraction
curr = w_intel.get("current", {})
temp = curr.get("temp", 25)
humidity = curr.get("humidity", 60)
wind = curr.get("wind", 0)
forecast = w_intel.get("forecast", [])
thresholds = farmer.get("threshold_settings", {})
rain_next_24h = any("rain" in d.get("description", "").lower() for d in forecast[:2])
heavy_rain_forecast = [d for d in forecast if "heavy" in d.get("description", "").lower()]
# ════════════════════════════════════════════════════════════════════════════
# 1️⃣ CRITICAL WEATHER ALERTS
# ════════════════════════════════════════════════════════════════════════════
if temp > thresholds.get("temp_high", 40):
alerts.append({
"type": "WEATHER",
"id": "EXTREME_HEAT",
"severity": SEVERITY_CRITICAL,
"title": "🌑️ EXTREME HEAT WARNING",
"message": f"Temperature reached {temp}Β°C. Immediate irrigation required.",
"action": "IRRIGATE_IMMEDIATELY",
"details": {
"current_temp": temp,
"threshold": thresholds.get("temp_high", 40),
"expected_crop_loss": "25-35%" if temp > 45 else "15-20%",
"hydration_urgency": "CRITICAL"
},
"action_items": [
f"🚨 Start irrigation within next 30 minutes",
"πŸ’§ Increase water supply by 20-30%",
"🌳 Consider temporary shade if available",
"πŸ“Š Monitor soil moisture every 2 hours"
]
})
if wind > thresholds.get("wind_speed", 30):
alerts.append({
"type": "WEATHER",
"id": "SEVERE_WIND",
"severity": SEVERITY_CRITICAL,
"title": "πŸŒͺ️ SEVERE WIND WARNING",
"message": f"Wind speed {wind} km/h. High crop damage risk.",
"action": "AVOID_ALL_OPERATIONS",
"details": {
"wind_speed": wind,
"risk_level": "CRITICAL",
"expected_damage": "Physical damage to plants, fruit drop"
},
"action_items": [
"β›” Stop all spraying and pesticide application",
"πŸ”§ Secure loose equipment and stakes",
"πŸ“ Postpone harvesting activities",
"🌾 Support weak branches with stakes"
]
})
if temp < thresholds.get("temp_low", 5):
alerts.append({
"type": "WEATHER",
"id": "FROST_RISK",
"severity": SEVERITY_HIGH,
"title": "❄️ FROST RISK - CROP PROTECTION NEEDED",
"message": f"Temperature dropping to {temp}Β°C. Frost damage imminent.",
"action": "PROTECT_CROP",
"details": {
"current_temp": temp,
"frost_risk": "HIGH",
"vulnerable_stages": "Flowering and young fruits"
},
"action_items": [
"πŸ”₯ Prepare frost protection measures (smudging/overhead irrigation)",
"πŸ’¨ Use wind machines if available",
"🌫️ Apply antitranspirants to sensitive crops",
"πŸ“ž Contact agricultural extension for emergency support"
]
})
# ════════════════════════════════════════════════════════════════════════════
# 2️⃣ HEAVY RAIN & FLOODING ALERTS
# ════════════════════════════════════════════════════════════════════════════
if heavy_rain_forecast:
alerts.append({
"type": "WEATHER",
"id": "HEAVY_RAIN_WARNING",
"severity": SEVERITY_HIGH,
"title": f"🌧️ HEAVY RAIN WARNING - {len(heavy_rain_forecast)} days",
"message": f"Heavy rainfall expected. Prepare drainage systems.",
"action": "PREPARE_DRAINAGE",
"details": {
"days_affected": len(heavy_rain_forecast),
"flooding_risk": "HIGH",
"drainage_priority": "URGENT"
},
"action_items": [
"πŸ’§ Clear all drainage channels and ditches",
"πŸ”¨ Repair broken drainage pipes immediately",
"πŸͺ΄ Avoid planting in low-lying areas",
"βš™οΈ Test pump systems before heavy rain",
"πŸ“Š Monitor water levels in fields"
]
})
if not rain_next_24h or wind > thresholds.get("wind_alert", 15):
alerts.append({
"type": "SPRAY_OPERATIONS",
"id": "UNSAFE_SPRAY_WINDOW",
"severity": SEVERITY_HIGH,
"title": "🚫 UNSAFE TO SPRAY",
"message": f"Rain or high wind (Wind: {wind} km/h). Postpone spraying.",
"action": "POSTPONE_SPRAYING",
"details": {
"wind_speed": wind,
"rain_probability": "HIGH",
"spray_loss_rate": "60-70%"
},
"action_items": [
"⏰ Postpone pesticide/fertilizer application",
"πŸ“… Reschedule for 3-5 days later",
"πŸ’° Higher wind causes 60-70% spray drift loss",
"πŸ“ Mark postponed tasks for follow-up"
]
})
elif not rain_next_24h and wind < thresholds.get("wind_alert", 15):
alerts.append({
"type": "SPRAY_OPERATIONS",
"id": "OPTIMAL_SPRAY_WINDOW",
"severity": SEVERITY_INFO,
"title": "βœ… OPTIMAL SPRAY WINDOW",
"message": "Ideal conditions for spraying. Good wind and no rain.",
"action": "APPLY_INPUTS",
"details": {
"wind_speed": wind,
"spray_efficiency": "95-98%",
"window_duration": "5-7 PM optimal"
},
"action_items": [
"⏱️ Plan spraying activities for 5-7 PM (optimal wind)",
"🎯 Use this window for pesticide/herbicide application",
"πŸ’‘ Higher efficiency = reduced chemical usage = cost savings",
"πŸ“Š Monitor weather updates continuously"
]
})
# ════════════════════════════════════════════════════════════════════════════
# 3️⃣ PEST & DISEASE ALERTS
# ════════════════════════════════════════════════════════════════════════════
for pest in p_intel.get("pest_prediction_table", []):
severity = pest.get("severity", "").upper()
pest_name = pest.get("pest_name", "Unknown Pest")
confidence = pest.get("confidence", 50)
if severity in ["CRITICAL", "HIGH"]:
alert_severity = SEVERITY_CRITICAL if severity == "CRITICAL" else SEVERITY_HIGH
alerts.append({
"type": "PEST_ALERT",
"id": f"PEST_{pest_name.upper().replace(' ', '_')}",
"severity": alert_severity,
"title": f"πŸ› {pest_name.upper()} ALERT",
"message": f"High {pest_name} infestation risk detected ({confidence}% confidence).",
"action": "PEST_MANAGEMENT",
"details": {
"pest": pest_name,
"risk_level": severity,
"confidence": confidence,
"favorable_temp": f"{temp}Β°C is {'FAVORABLE' if 20 <= temp <= 30 else 'UNFAVORABLE'} for {pest_name}",
"humidity_level": f"Current: {humidity}% - {'High risk' if humidity > 70 else 'Moderate risk'}"
},
"action_items": [
f"πŸ” Scout fields immediately for {pest_name} symptoms",
f"πŸ§ͺ Start bioagent/chemical control within 48 hours",
f"πŸ“Έ Document infestation level (% affected plants)",
f"πŸ“ž Contact agricultural extension for spray recommendations",
f"⏰ Plan early morning or late evening spraying (5-7 PM optimal)"
]
})
# ════════════════════════════════════════════════════════════════════════════
# 4️⃣ IRRIGATION MANAGEMENT ALERTS
# ════════════════════════════════════════════════════════════════════════════
water_m3 = water_intel.get("water_m3_sqm", 0)
irrigation_minutes = water_intel.get("irrigation_minutes", 0)
if water_m3 > 0.15 or (temp > 35 and water_m3 > 0.1):
alerts.append({
"type": "IRRIGATION",
"id": "IMMEDIATE_IRRIGATION_NEEDED",
"severity": SEVERITY_CRITICAL if temp > 35 else SEVERITY_HIGH,
"title": "πŸ’§ IRRIGATION REQUIRED",
"message": f"Soil water deficit: {water_m3:.3f} mΒ³. Start irrigation NOW.",
"action": "IRRIGATE_IMMEDIATELY",
"details": {
"water_needed": f"{water_m3:.3f} mΒ³/mΒ²",
"irrigation_duration_minutes": round(irrigation_minutes),
"soil_moisture_status": "CRITICAL" if water_m3 > 0.15 else "LOW",
"temperature_stress": "YES" if temp > 35 else "NO"
},
"action_items": [
f"⏱️ Start irrigation for {round(irrigation_minutes)} minutes",
f"πŸ’§ Deliver {water_m3:.2f} mΒ³ per mΒ² of field",
"🌑️ Best timing: Early morning (5-7 AM) or evening (6-8 PM)",
"πŸ“Š Check soil moisture after irrigation completion",
"πŸ“ˆ Monitor evapotranspiration for next irrigation schedule"
]
})
elif 0.05 < water_m3 <= 0.15:
alerts.append({
"type": "IRRIGATION",
"id": "IRRIGATION_SCHEDULED",
"severity": SEVERITY_MEDIUM,
"title": "πŸ’§ IRRIGATION SCHEDULED",
"message": f"Plan irrigation soon. Water needed: {water_m3:.3f} mΒ³",
"action": "SCHEDULE_IRRIGATION",
"details": {
"water_needed": f"{water_m3:.3f} mΒ³/mΒ²",
"irrigation_duration_minutes": round(irrigation_minutes),
"best_window": "Next 48-72 hours"
},
"action_items": [
f"πŸ“… Schedule irrigation in next 2-3 days",
f"⏱️ Duration: {round(irrigation_minutes)} minutes",
f"πŸ’§ Water quantity: {water_m3:.2f} mΒ³/mΒ²",
"🌞 Avoid midday irrigation (high evaporation)",
"🧹 Remove weeds before irrigation (better water use)"
]
})
else:
alerts.append({
"type": "IRRIGATION",
"id": "IRRIGATION_OPTIMAL",
"severity": SEVERITY_INFO,
"title": "βœ… SOIL MOISTURE OPTIMAL",
"message": "Current soil moisture is adequate. Monitor regularly.",
"action": "MONITOR",
"details": {
"water_status": "OPTIMAL",
"next_check": "48 hours"
}
})
# ════════════════════════════════════════════════════════════════════════════
# 5️⃣ CLIMATE RESILIENCE & SUSTAINABILITY ALERTS
# ════════════════════════════════════════════════════════════════════════════
resilience = calculate_climate_resilience_score(w_intel, p_intel, water_intel, farmer)
if resilience["total_score"] < 50:
alerts.append({
"type": "CLIMATE_RESILIENCE",
"id": "LOW_RESILIENCE_ALERT",
"severity": SEVERITY_HIGH,
"title": "⚠️ LOW CLIMATE RESILIENCE INDEX",
"message": f"Farm resilience score: {resilience['total_score']:.0f}/100. Multiple risks detected.",
"action": "IMPLEMENT_RESILIENCE_MEASURES",
"details": resilience,
"action_items": [
"🌾 Implement mulching to reduce water loss 30-40%",
"🌱 Plant nitrogen-fixing legumes for soil health",
"πŸ’¨ Establish windbreaks for wind protection",
"πŸ”„ Diversify crops to reduce single-pest risk",
"πŸ’° Consider insurance schemes for climate risks"
]
})
# Sustainability Tips based on conditions
if irrigation_minutes > 40:
alerts.append({
"type": "SUSTAINABILITY",
"id": "WATER_CONSERVATION_TIP",
"severity": SEVERITY_INFO,
"title": "πŸ’§ WATER CONSERVATION OPPORTUNITY",
"message": "High irrigation need. Implement water-saving techniques.",
"action": "CONSERVATION_MEASURE",
"details": {
"current_irrigation_time": round(irrigation_minutes),
"potential_savings": "30-40%"
},
"action_items": [
"🌾 Apply mulch (straw/leaves) to reduce evaporation by 40%",
"🌱 Use drip irrigation if available (saves 50% water vs. flood)",
"πŸ’¨ Install wind breaks to reduce evaporative stress",
"πŸ• Irrigate early morning (5-7 AM) to minimize evaporation",
"πŸ“Š Monitor soil moisture with meter for precision"
]
})
else:
alerts.append({
"type": "SUSTAINABILITY",
"id": "SUSTAINABLE_PRACTICE_TIP",
"severity": SEVERITY_INFO,
"title": "🌍 SUSTAINABLE FARMING TIP",
"message": "Implement intercropping for natural pest control.",
"action": "IMPLEMENT_PRACTICE",
"details": {
"practice": "Intercropping with legumes",
"benefit": "30-40% reduction in pest incidence, soil nitrogen boost"
},
"action_items": [
"🌱 Intercrop with legumes (beans, peas) to fix nitrogen",
"🐝 Attract pollinators with flowering plants at field edges",
"πŸ› Encourage beneficial insects (ladybugs, parasitoid wasps)",
"♻️ Use crop residue for compost instead of burning",
"πŸ“ˆ Expected yield increase: 15-20% with better soil health"
]
})
logger.info(f"βœ… Generated {len(alerts)} alerts for {farmer.get('name', 'Farmer')}")
return alerts