from flask import Flask, render_template, request, redirect, url_for, session,jsonify import joblib import pandas as pd import numpy as np import requests import json import os import plotly.graph_objects as go app = Flask(__name__) # Load the SVM model svm_poly_model = joblib.load('svm_poly_model.pkl') # Label encoding mappings for SVM model crop_type_mapping = { 'BANANA': 0, 'BEAN': 1, 'CABBAGE': 2, 'CITRUS': 3, 'COTTON': 4, 'MAIZE': 5, 'MELON': 6, 'MUSTARD': 7, 'ONION': 8, 'OTHER': 9, 'POTATO': 10, 'RICE': 11, 'SOYABEAN': 12, 'SUGARCANE': 13, 'TOMATO': 14, 'WHEAT': 15 } soil_type_mapping = {'DRY': 0, 'HUMID': 1, 'WET': 2} weather_condition_mapping = {'NORMAL': 0, 'RAINY': 1, 'SUNNY': 2, 'WINDY': 3} # Fetch weather data from the OpenWeatherMap API def get_weather(city): api_key=os.getenv('WEATHER_API') url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}" try: response = requests.get(url) response.raise_for_status() # Raise an exception for any HTTP errors except requests.exceptions.HTTPError as err: return None, None, None, None try: data = json.loads(response.text) if data['cod'] != 200: return None, None, None, None except json.JSONDecodeError as err: return None, None, None, None # Extract relevant weather information weather_description = data['weather'][0]['description'] temperature = data['main']['temp'] humidity = data['main']['humidity'] pressure = data['main']['pressure'] # Convert temperature from Kelvin to Celsius temperature = round(temperature - 273.15, 2) return temperature, humidity, weather_description, pressure @app.route('/') def index(): return render_template('index.html') @app.route('/fetch_weather', methods=['GET']) def fetch_weather(): city = request.args.get('city') if city: temperature, humidity, weather_description, pressure = get_weather(city) if temperature is not None: return json.dumps({ 'description': weather_description.capitalize(), 'temperature': temperature, 'humidity': humidity, 'pressure': pressure }) return json.dumps(None) # Return None if weather couldn't be fetched @app.route('/predict', methods=['POST']) def predict(): if request.method == 'POST': crop_type = request.form['crop_type'] soil_type = request.form['soil_type'] city = request.form['city'] motor_capacity = float(request.form['motor_capacity']) # Get weather data temperature, humidity, weather_description, pressure = get_weather(city) # Auto-fill weather condition based on description if temperature is None: auto_weather_condition = 'NORMAL' temperature = 32.0 else: auto_weather_condition = ('SUNNY' if 'clear' in weather_description.lower() else 'RAINY' if 'rain' in weather_description.lower() else 'WINDY' if 'wind' in weather_description.lower() else 'NORMAL') # Encode inputs for the model crop_type_encoded = crop_type_mapping[crop_type] soil_type_encoded = soil_type_mapping[soil_type] weather_condition_encoded = weather_condition_mapping[auto_weather_condition] # Create DataFrame for input user_data = pd.DataFrame({ 'CROP TYPE': [crop_type_encoded], 'SOIL TYPE': [soil_type_encoded], 'TEMPERATURE': [temperature], 'WEATHER CONDITION': [weather_condition_encoded] }) # Predict water requirement water_requirement = svm_poly_model.predict(user_data)[0] # Calculate estimated time duration estimated_time_duration = water_requirement / motor_capacity if motor_capacity > 0 else 0 time_unit = "seconds" if estimated_time_duration < 1 else "minutes" estimated_time_duration = estimated_time_duration * 60 if time_unit == "seconds" else estimated_time_duration # Create the gauge charts for water requirement and estimated time water_gauge = go.Figure(go.Indicator( mode="gauge+number", value=water_requirement, title={"text": "Water Requirement (m³/sq.m)"}, gauge={ "axis": {"range": [None, 100]}, "bar": {"color": "blue"}, "steps": [ {"range": [0, 20], "color": "lightgray"}, {"range": [20, 50], "color": "yellow"}, {"range": [50, 100], "color": "green"} ] } )) # Determine gauge axis range based on the time unit max_range = 60 if time_unit == "seconds" else 120 time_gauge = go.Figure(go.Indicator( mode="gauge+number", value=round(estimated_time_duration, 2), title={"text": f"Estimated Time ({time_unit.capitalize()})"}, gauge={ "axis": {"range": [None, max_range]}, "bar": {"color": "blue"}, "steps": [ {"range": [0, max_range * 0.33], "color": "lightgray"}, {"range": [max_range * 0.33, max_range * 0.66], "color": "yellow"}, {"range": [max_range * 0.66, max_range], "color": "green"} ] } )) # Send gauge charts to the prediction page water_gauge_path = water_gauge.to_html(full_html=False) time_gauge_path = time_gauge.to_html(full_html=False) return render_template('predict.html', water_requirement=round(water_requirement, 2), estimated_time_duration=round(estimated_time_duration, 2), time_unit=time_unit, weather_info=f"Weather in {city}: {weather_description.capitalize()}
" f"Temperature: {temperature}°C
" f"Humidity: {humidity}%
" f"Pressure: {pressure} hPa
", water_gauge=water_gauge_path, time_gauge=time_gauge_path) return redirect(url_for('index')) @app.route('/start_motor', methods=['POST']) def start_motor(): estimated_time_duration = float(request.json.get('estimated_time_duration')) time_unit = request.json.get('time_unit', 'seconds') # Default unit is seconds # Convert time to seconds if it's in minutes if estimated_time_duration < 10: estimated_time_duration_seconds = estimated_time_duration * 60 else: estimated_time_duration_seconds = estimated_time_duration # Assuming this function will trigger the motor start, we will just send the confirmation print(f"Starting motor for {estimated_time_duration_seconds} seconds") # Return a response indicating that the motor has started return jsonify({"status": "motor_started", "estimated_time_duration": estimated_time_duration_seconds}) if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)