File size: 13,286 Bytes
0ee27f7
5fd7795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0ee27f7
 
 
5fd7795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970be68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5fd7795
970be68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
from typing import List, Optional, Dict, Any
from pydantic import BaseModel, Field
from datetime import datetime, timezone


def current_utc_time():
    return datetime.now(timezone.utc)


class AlternativeDiagnosis(BaseModel):
    disease_id: str
    disease_name: str
    crop: str
    confidence: float = Field(..., ge=0.0, le=1.0)


class TreatmentPlan(BaseModel):
    immediate_action: List[str]
    organic_control: List[str]
    chemical_control: List[str]


class DiseaseDetail(BaseModel):
    id: str
    name: str
    scientific_name: Optional[str] = None
    crop: str
    severity: str = Field(..., description="Healthy | Low | Moderate | Severe | Critical | Invalid")
    is_healthy: bool = False
    symptoms: List[str]
    treatment: TreatmentPlan
    prevention: List[str]
    expert_consultation_recommended: bool = False


class DiagnosisResponse(BaseModel):
    success: bool = True
    is_valid_leaf: bool = Field(default=True, description="False if image is a car, object, or non-plant")
    timestamp: datetime = Field(default_factory=current_utc_time)
    image_id: str
    crop: str
    disease: str
    disease_id: str
    scientific_name: Optional[str] = None
    is_healthy: bool
    severity: str
    confidence: float = Field(..., ge=0.0, le=1.0)
    confidence_percentage: str
    symptoms: List[str]
    management: TreatmentPlan
    prevention: List[str]
    alternatives: List[AlternativeDiagnosis] = []
    similar_crops: List[str] = []
    expert_escalation: dict = Field(
        default_factory=lambda: {
            "recommended": False,
            "helpline_number": "+918817814859",
            "whatsapp_expert": "+918817814859",
            "reason": None
        }
    )


class CropInfo(BaseModel):
    crop_name: str
    supported_diseases_count: int
    diseases: List[str]


class SupportedCropsResponse(BaseModel):
    total_crops: int
    total_classes: int
    crops: List[CropInfo]


class ExpertTicketRequest(BaseModel):
    farmer_name: str
    phone_number: str
    location: Optional[str] = None
    crop: str
    disease_suspected: Optional[str] = None
    confidence_score: Optional[float] = None
    notes: Optional[str] = None
    image_url_or_id: Optional[str] = None


class ExpertTicketResponse(BaseModel):
    ticket_id: str
    status: str = "PENDING_REVIEW"
    created_at: datetime = Field(default_factory=current_utc_time)
    message: str
    assigned_expert: str = "Dr. S. Sharma (Senior Agronomist, Plant Pathology)"
    estimated_callback_minutes: int = 30


class DosageCalculationRequest(BaseModel):
    crop: str
    disease_id: str
    farm_area_acres: float = Field(..., gt=0.0, description="Farm area in acres")
    knapsack_tank_liters: float = Field(default=16.0, gt=0.0, description="Knapsack sprayer tank capacity in liters")
    treatment_type: str = Field(default="chemical", description="chemical | organic")


class DosageCalculationResponse(BaseModel):
    crop: str
    disease: str
    farm_area_acres: float
    recommended_chemical_or_bio: str
    total_water_liters: float
    total_dosage_amount: str
    dosage_per_tank: str
    total_knapsack_tanks: int
    spray_instructions: List[str]
    safety_precautions: List[str]


class SporeCastPoint(BaseModel):
    district: str
    latitude: float
    longitude: float
    disease: str
    risk_level: str  # Low, Moderate, High, Severe Epidemic
    wind_vector: str
    forecast_48h: str
    affected_farms_reported: int


class SporeCastAlertResponse(BaseModel):
    active_epidemics: int
    highest_risk_region: str
    spore_dispersion_speed_kmh: float
    regional_heatmap: List[SporeCastPoint]
    kvk_advisory: str


class GreenCreditRequest(BaseModel):
    farmer_id: Optional[str] = "FARMER-001"
    crop: str
    farm_area_acres: float
    adopted_practice: str = Field(..., description="bio_fungicide | neem_extract | trichoderma | balanced_ipm")


class GreenCreditResponse(BaseModel):
    green_credits_earned: int
    chemical_pesticide_saved_kg: float
    carbon_offset_kg_co2e: float
    soil_microbiome_health_score: str
    reward_redemption_eligible: bool
    certificate_id: str


class SpectroscopyAnalysisResponse(BaseModel):
    is_leaf: bool = True
    is_valid_leaf: bool = True
    rejection_code: Optional[str] = None
    error_message: Optional[str] = None
    chlorophyll_retention_percentage: float = 0.0
    green_leaf_index_gli: float = 0.0
    vari_index: float = 0.0
    ngrdi_index: float = 0.0
    health_status: str
    asymptomatic_stress_detected: bool = False
    risk_classification: str
    spectral_diagnosis: str
    early_action_protocol: List[str] = []
    foliage_coverage_percentage: Optional[float] = None
    diagnostics: Optional[dict] = None


class FarmMemorySaveRequest(BaseModel):
    crop: str
    disease: str
    disease_id: str
    severity: str
    confidence: float
    temperature_c: float
    humidity_pct: float
    weather_condition: str
    location_name: Optional[str] = "Ambikapur, Surguja"
    gps_lat: Optional[float] = 23.1188
    gps_lng: Optional[float] = 83.1979
    farmer_notes: Optional[str] = ""
    diagnosis_date: Optional[str] = None


class SeasonalAlertItem(BaseModel):
    alert_id: str
    crop: str
    disease: str
    disease_id: str
    historical_outbreak_date: str
    threat_level: str
    recurrence_risk_score: float
    window_description: str
    alert_title: str
    alert_message: str
    prophylactic_plan: dict


class SeasonalAlertsResponse(BaseModel):
    status: str = "success"
    active_alerts_count: int
    alerts: List[SeasonalAlertItem]


class BioAcousticAnalysisResponse(BaseModel):
    pest_detected: bool
    pest_identified: str
    threat_level: str
    confidence_score: float
    dominant_frequency_hz: float
    pest_acoustic_energy_ratio: float
    diagnosis_summary: str
    recommended_actions: List[str]
    engine_type: Optional[str] = "Mel_CNN_BioAcoustic"
    class_probabilities: Optional[Dict[str, float]] = None
    mastication_rhythm_index: Optional[float] = None


class BioTwinForecastResponse(BaseModel):
    crop: str
    target_pathogen: str
    spore_germination_index_pct: float
    risk_classification: str
    calculated_dew_point_c: float
    effective_leaf_wetness_hours: float
    critical_infection_window_hours: int
    physics_forecast_summary: str
    preventive_canopy_actions: List[str]


class DroneVRAMissionRequest(BaseModel):
    field_id: str = "FIELD-01"
    center_lat: float = 23.1188
    center_lng: float = 83.1979
    field_area_acres: float = Field(..., gt=0.0)
    infected_clusters: List[dict] = Field(default_factory=list)
    spray_altitude_meters: float = Field(default=2.5, gt=0.5, le=10.0)


class DroneVRAMissionResponse(BaseModel):
    mission_id: str
    field_area_acres: float
    flight_altitude_meters: float
    swath_width_meters: float
    total_waypoints: int
    estimated_flight_duration_minutes: float
    vra_spot_spray_liters: float
    traditional_blanket_spray_liters: float
    chemical_savings_percentage: str
    waypoints: List[dict]
    geojson_flight_plan: dict
    qgroundcontrol_format_compatible: bool


class ProofOfFarmingRequest(BaseModel):
    farmer_id: str = "FARMER-101"
    farmer_name: str
    khasra_survey_number: str
    district: str = "Surguja"
    state: str = "Chhattisgarh"
    crop: str = "Paddy (Rice)"
    disease_identified: str
    severity_percentage: float = Field(..., ge=0.0, le=100.0)
    affected_area_acres: float = Field(..., gt=0.0)
    gps_latitude: float
    gps_longitude: float
    image_hash: Optional[str] = None


class ProofOfFarmingResponse(BaseModel):
    certificate_id: str
    digital_signature_sha256: str
    created_at_utc: str
    claim_status: str
    fast_track_claim_payload: dict
    blockchain_smart_contract_ready: bool
    verification_qr_payload: str


class GovernmentSchemeItem(BaseModel):
    id: str
    title_hi: str
    title_en: str
    category: str
    category_hi: str
    benefit_amount: str
    summary_hi: str
    summary_en: str
    eligibility_hi: str
    required_documents_hi: List[str]
    official_portal: str
    direct_apply_url: Optional[str] = None
    status_check_url: Optional[str] = None
    guidelines_pdf_url: Optional[str] = None
    source_portal_authority: Optional[str] = "Government of India"
    helpline: str
    icon: str
    badge_color: str
    last_synced_utc: Optional[str] = None


class GovernmentSchemesResponse(BaseModel):
    total_schemes: int
    myscheme_portal_url: str = "https://www.myscheme.gov.in/search/category/Agriculture,Rural%20&%20Environment"
    live_sync_status: str = "SYNCED_WITH_GOVT_PORTALS"
    categories: List[str]
    schemes: List[GovernmentSchemeItem]


class KisanPollOptionItem(BaseModel):
    id: str
    title_hi: str
    title_en: str
    description_hi: str
    icon: str
    votes_count: int
    vote_percentage: float
    recommended_govt_action_hi: str


class KisanPollVoteRequest(BaseModel):
    problem_id: str
    district: Optional[str] = "Surguja"
    state: Optional[str] = "Chhattisgarh"
    crop_affected: Optional[str] = "Paddy (Rice)"
    farmer_comment: Optional[str] = ""


class KisanPollResultsResponse(BaseModel):
    target_district: str
    total_farmer_responses: int
    highest_priority_issue: str
    highest_priority_vote_share: str
    recommended_immediate_intervention: str
    issues_breakdown: List[KisanPollOptionItem]
    last_updated: str


# =========================================================================
# Next-Gen Innovation Schemas (Voice, Traps, Satellite, Soil, GNN)
# =========================================================================
class VoiceAdvisoryRequest(BaseModel):
    user_query: str
    dialect: Optional[str] = "ch-IN"
    crop: Optional[str] = None


class VoiceAdvisoryResponse(BaseModel):
    status: str = "success"
    dialect: str
    dialect_name: str
    user_query: str
    normalized_context: dict
    spoken_title: str
    advisory_text: str
    tank_prescription: dict
    tts_playback_metadata: dict



class SoilHealthCardRequest(BaseModel):
    crop: Optional[str] = "Rice"
    area_acres: Optional[float] = 1.0
    ph: Optional[float] = 6.8
    organic_carbon_pct: Optional[float] = 0.52
    available_n_kg_ha: Optional[float] = 220.0
    available_p_kg_ha: Optional[float] = 14.5
    available_k_kg_ha: Optional[float] = 180.0
    zinc_ppm: Optional[float] = 0.55
    has_active_blast: Optional[bool] = False


class SoilHealthCardResponse(BaseModel):
    status: str = "success"
    soil_test_readings: dict
    target_crop: str
    area_acres: float
    total_commercial_fertilizer: dict
    split_schedule: List[dict]
    safety_alert: Optional[str] = None



# =========================================================================
# Extreme Weather Shock & IoT Telemetry Schemas
# =========================================================================
class WeatherShockForecastRequest(BaseModel):
    crop: Optional[str] = "Potato"
    ambient_temp_c: Optional[float] = 4.0
    min_predicted_temp_c: Optional[float] = 1.5
    max_predicted_temp_c: Optional[float] = 24.0
    relative_humidity: Optional[float] = 55.0
    wind_speed_kmh: Optional[float] = 3.0
    cloud_cover_pct: Optional[float] = 5.0
    growth_stage: Optional[str] = None


class WeatherShockForecastResponse(BaseModel):
    status: str = "success"
    crop: str
    vulnerable_stage: str
    primary_threat: str
    microclimate_snapshot: dict
    frost_assessment: dict
    heatwave_assessment: dict


class IoTTelemetryPacket(BaseModel):
    device_id: str = "NODE-SURGUJA-01"
    battery_voltage_v: float = 3.92
    solar_charging: bool = True
    rssi_dbm: int = -88
    snr_db: float = 8.5
    soil_moisture_vwc_15cm: float = 24.5
    soil_moisture_vwc_30cm: float = 28.2
    canopy_temp_c: float = 26.4
    canopy_rh_pct: float = 82.0
    leaf_wetness_pct: float = 45.0


class IoTTelemetryResponse(BaseModel):
    status: str = "success"
    device_id: str
    packet_timestamp_utc: str
    soil_moisture_assessment: dict
    microclimate: dict
    hardware_telemetry: dict
    active_alarms: List[dict]


# =========================================================================
# Kisan Jan-Mat Community Poll & Government Scheme Schemas
# =========================================================================
class KisanPollVoteRequest(BaseModel):
    problem_id: str
    district: Optional[str] = "Surguja"
    state: Optional[str] = "Chhattisgarh"
    crop_affected: Optional[str] = "Paddy (Rice)"
    farmer_comment: Optional[str] = ""
    device_id: Optional[str] = ""


class KisanPollVoteResponse(BaseModel):
    status: str
    message_hi: str
    message_en: str
    ballot_id: str
    total_community_votes: int
    updated_results: List[dict]


class KisanPollQuestionsResponse(BaseModel):
    status: str = "success"
    total_options: int
    options: List[dict]


class KisanPollResultsResponse(BaseModel):
    status: str = "success"
    target_district: str
    total_farmer_responses: int
    highest_priority_issue: str
    highest_priority_vote_share: str
    recommended_immediate_intervention: str
    issues_breakdown: List[dict]
    recent_grassroot_ballots: Optional[List[dict]] = []
    last_updated: str