File size: 6,159 Bytes
73f907e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from flask import Flask, render_template, request, jsonify
import requests
import google.generativeai as genai
import os
import json

app = Flask(__name__)

# Mapping of SoilGrids parameter codes
PARAM_MAP = {
    "bdod": "Bulk Density", "cec": "Cation Exchange Capacity", "cfvo": "Coarse Fragment Volume",
    "clay": "Clay Content", "nitrogen": "Nitrogen Content", "ocd": "Organic Carbon Density",
    "ocs": "Organic Carbon Stock", "phh2o": "Soil pH", "sand": "Sand Content",
    "silt": "Silt Content", "soc": "Soil Organic Carbon", "wv0010": "Water Content (0-10cm)",
    "wv0033": "Water Content (0-33cm)", "wv1500": "Water Content (1500mm)"
}

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/get_soil_report', methods=['POST'])
def get_soil_report():
    data = request.get_json()
    lat, lon = data.get("lat"), data.get("lon")
    if not lat or not lon:
        return jsonify({"error": "Latitude and Longitude are required"}), 400

    headers = {"accept": "application/json"}
    
    # Fetch Soil Classification
    try:
        class_response = requests.get(
            "https://rest.isric.org/soilgrids/v2.0/classification/query",
            params={"lon": lon, "lat": lat, "number_classes": 5},
            headers=headers, timeout=15
        )
        class_response.raise_for_status()
        class_data = class_response.json()
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"Failed to fetch soil classification: {e}"}), 500

    soil_classification = {
        "soil_type": class_data.get("wrb_class_name", "Unknown"),
        "probabilities": class_data.get("wrb_class_probability", [])
    }

    # Fetch Soil Properties
    try:
        prop_response = requests.get(
            "https://rest.isric.org/soilgrids/v2.0/properties/query",
            params={
                "lon": lon, "lat": lat,
                "property": list(PARAM_MAP.keys()),
                "depth": "5-15cm", "value": "mean"
            },
            headers=headers, timeout=15
        )
        prop_response.raise_for_status()
        prop_data = prop_response.json()
    except requests.exceptions.RequestException as e:
        return jsonify({"error": f"Failed to fetch soil properties: {e}"}), 500

    properties_list = []
    layers = prop_data.get("properties", {}).get("layers", [])
    for layer in layers:
        param_code = layer.get("name")
        name = PARAM_MAP.get(param_code, param_code.upper())
        depth_info = layer.get("depths", [{}])[0]
        value = depth_info.get("values", {}).get("mean")
        unit = layer.get("unit_measure", {}).get("mapped_units", "")

        if value is not None:
            if param_code == "phh2o":
                value /= 10.0
                unit = "pH"
            elif param_code in ["wv0010", "wv0033", "wv1500"]:
                 value /= 100.0
                 unit = "cm³/cm³"

        properties_list.append({"parameter": name, "value": value, "unit": unit})

    return jsonify({"classification": soil_classification, "properties": properties_list})

@app.route('/analyze_soil', methods=['POST'])
def analyze_soil():
    api_key = os.getenv("GEMINI_API")
    if not api_key:
        error_msg = "API key not configured. The server administrator must set the GEMINI_API environment variable."
        return jsonify({"error": error_msg}), 500

    data = request.get_json()
    soil_report = data.get("soil_report")
    language = data.get("language", "English")
    
    if not soil_report:
        return jsonify({"error": "Soil report data is missing"}), 400

    prompt = f"""

    Analyze the following soil report and provide recommendations.

    The response MUST be a single, valid JSON object, without any markdown formatting or surrounding text.

    The user wants the analysis in this language: {language}.

    Soil Report Data: {json.dumps(soil_report, indent=2)}

    JSON Structure to follow:

    {{

      "soilType": "The primary soil type from the report",

      "generalInsights": ["Insight 1", "Insight 2", "Insight 3"],

      "parameters": [{{"parameter": "Parameter Name", "value": "Value with Unit", "range": "Low/Normal/High", "comment": "Brief comment."}}],

      "cropRecommendations": [{{"crop": "Crop Name", "reason": "Brief reason."}}],

      "managementRecommendations": {{"fertilization": "Recommendation.", "irrigation": "Recommendation."}}

    }}

    """

    try:
        genai.configure(api_key=api_key)
        
        # --- NEW: Fallback Logic Implementation ---
        models_to_try = ['gemini-2.5-flash', 'gemini-2.0-flash', 'gemini-1.5-flash']
        analysis_json = None
        last_error = None

        for model_name in models_to_try:
            try:
                print(f"Attempting to use model: {model_name}")
                model = genai.GenerativeModel(model_name)
                response = model.generate_content(prompt)
                
                cleaned_response = response.text.strip().replace("```json", "").replace("```", "")
                analysis_json = json.loads(cleaned_response)
                
                print(f"Successfully generated content with {model_name}")
                break  # Exit the loop on success
            
            except Exception as e:
                print(f"Model {model_name} failed: {e}")
                last_error = e
                continue # Try the next model in the list

        if not analysis_json:
            # This block is reached only if all models in the loop failed.
            raise Exception("All specified AI models failed to generate a response.") from last_error

        return jsonify(analysis_json)

    except Exception as e:
        # This catches the final error if all models fail, or any other setup error.
        print(f"Error during Gemini API processing: {e}")
        return jsonify({"error": f"Failed to get analysis from AI models: {e}"}), 500

if __name__ == '__main__':
    app.run(debug=True, port=7860)