ShrishtiAI-backend / server /controllers /weatherwise_prediction_controller.py
MEWTROS
My 6 can be your 9
5ccd893
"""
WeatherWise Prediction Controller
Handles HTTP requests for LSTM weather forecasting
"""
import logging
from typing import Dict, Any
from datetime import datetime
from services.weatherwise_prediction_service import WeatherWisePredictionService
logger = logging.getLogger(__name__)
class WeatherWisePredictionController:
"""Controller for handling WeatherWise LSTM weather forecasting requests"""
def __init__(self, weatherwise_service: WeatherWisePredictionService = None):
"""Initialize WeatherWise controller"""
self.service = weatherwise_service or WeatherWisePredictionService()
self.controller_stats = {
'controller_start_time': datetime.now().isoformat(),
'total_requests': 0,
'successful_requests': 0,
'failed_requests': 0
}
logger.info("WeatherWise prediction controller initialized")
def initialize_controller(self) -> Dict[str, Any]:
"""
Initialize the controller by setting up the WeatherWise service
Returns:
Initialize response dictionary
"""
try:
logger.info("Initializing WeatherWise prediction controller...")
# Initialize the WeatherWise service
service_success, service_message = self.service.initialize_service()
if service_success:
available_models = self.service.get_available_models()
logger.info(f"[SUCCESS] WeatherWise controller initialized with {len(available_models)} models")
return self._create_response(
success=True,
message="WeatherWise controller initialized successfully",
data={
'service_status': 'initialized',
'available_models': available_models,
'default_forecast_days': 60,
'supported_variables': self.service.prediction_model.forecast_variables
}
)
else:
logger.error(f"[ERROR] WeatherWise service initialization failed: {service_message}")
return self._create_response(
success=False,
message="WeatherWise controller initialization failed",
error=service_message
)
except Exception as e:
logger.error(f"WeatherWise controller initialization error: {e}")
return self._create_response(
success=False,
message="WeatherWise controller initialization error",
error=f"Controller error: {str(e)}"
)
def forecast_weather(self, request_data: Dict[str, Any]) -> Dict[str, Any]:
"""
Generate weather forecast for location
Args:
request_data: Request dictionary with latitude, longitude, etc.
Returns:
Forecast response dictionary
"""
self.controller_stats['total_requests'] += 1
try:
logger.info(f"[WEATHERWISE_CONTROLLER] ===== FORECAST REQUEST START =====")
logger.info(f"[WEATHERWISE_CONTROLLER] Processing forecast request...")
logger.info(f"[WEATHERWISE_CONTROLLER] Total requests so far: {self.controller_stats['total_requests']}")
# Extract request parameters
latitude = request_data.get('latitude')
longitude = request_data.get('longitude')
reference_date = request_data.get('reference_date')
disaster_type = request_data.get('disaster_type', 'Normal')
forecast_days = request_data.get('forecast_days', 60)
logger.info(f"[WEATHERWISE_CONTROLLER] Extracted parameters:")
logger.info(f"[WEATHERWISE_CONTROLLER] - latitude: {latitude}")
logger.info(f"[WEATHERWISE_CONTROLLER] - longitude: {longitude}")
logger.info(f"[WEATHERWISE_CONTROLLER] - reference_date: {reference_date}")
logger.info(f"[WEATHERWISE_CONTROLLER] - disaster_type: {disaster_type}")
logger.info(f"[WEATHERWISE_CONTROLLER] - forecast_days: {forecast_days}")
# Reject if TF models are still warming up in the background thread
if not self.service.service_stats.get('models_loaded'):
return self._create_response(
success=False,
message="Service is warming up, please retry in a moment",
error="models_not_ready"
)
# Validate required parameters
if latitude is None or longitude is None:
logger.error("[WEATHERWISE_CONTROLLER] Missing required parameters")
return self._create_response(
success=False,
message="Missing required parameters",
error="Both 'latitude' and 'longitude' are required"
)
logger.info(f"[WEATHERWISE_CONTROLLER] Parameters validated successfully")
# Validate disaster type
available_models = self.service.get_available_models()
if disaster_type not in available_models and available_models:
logger.warning(f"Requested disaster type '{disaster_type}' not available, using '{available_models[0]}'")
disaster_type = available_models[0]
# Validate forecast days
try:
forecast_days = int(forecast_days)
if forecast_days < 1 or forecast_days > 365:
forecast_days = 60 # Default
except (ValueError, TypeError):
forecast_days = 60
logger.info(f"[WEATHERWISE_CONTROLLER] Calling service.generate_weather_forecast()...")
logger.info(f"Processing weather forecast for ({latitude}, {longitude})")
logger.info(f"Parameters: disaster_type={disaster_type}, forecast_days={forecast_days}, reference_date={reference_date}")
# Generate forecast using service
forecast_result = self.service.generate_weather_forecast(
latitude=latitude,
longitude=longitude,
reference_date=reference_date,
disaster_type=disaster_type,
forecast_days=forecast_days
)
logger.info(f"[WEATHERWISE_CONTROLLER] Service call completed")
logger.info(f"[WEATHERWISE_CONTROLLER] Forecast result success: {forecast_result.get('success')}")
if forecast_result['success']:
self.controller_stats['successful_requests'] += 1
response_data = {
'forecast': forecast_result['weather_forecast'],
'forecast_dates': forecast_result['forecast_dates'],
'forecast_variables': forecast_result['forecast_variables'],
'model_context': forecast_result['model_type'],
'location': forecast_result['location'],
'forecast_summary': {
'horizon_days': forecast_result['forecast_horizon_days'],
'variables_count': len(forecast_result['forecast_variables']),
'model_used': forecast_result['model_type']
},
'data_collection_summary': forecast_result.get('data_collection', {})
}
return self._create_response(
success=True,
message="Weather forecast generated successfully",
data=response_data,
processing_info={
'processing_time_seconds': forecast_result.get('processing_time_seconds', 0),
'forecast_model': forecast_result['model_type'],
'forecast_horizon_days': forecast_result['forecast_horizon_days'],
'data_sources': forecast_result.get('processing_info', {}).get('data_sources', [])
}
)
else:
self.controller_stats['failed_requests'] += 1
return self._create_response(
success=False,
message="Weather forecast generation failed",
error=forecast_result.get('error', 'Unknown forecast error'),
data={
'location': forecast_result.get('location'),
'processing_time_seconds': forecast_result.get('processing_time_seconds', 0)
}
)
except Exception as e:
self.controller_stats['failed_requests'] += 1
logger.error(f"WeatherWise controller forecast error: {e}")
return self._create_response(
success=False,
message="Weather forecast error",
error=f"Controller error: {str(e)}"
)
def get_service_status(self) -> Dict[str, Any]:
"""
Get WeatherWise service status and health information
Returns:
Service status response
"""
try:
# Get service health from the service layer
service_health = self.service.get_service_health()
# Add controller statistics
response_data = {
'controller_info': {
'controller_name': 'WeatherWise Prediction Controller',
'controller_stats': self.controller_stats
},
'service_health': service_health
}
return self._create_response(
success=True,
message="WeatherWise service status retrieved successfully",
data=response_data
)
except Exception as e:
logger.error(f"WeatherWise status error: {e}")
return self._create_response(
success=False,
message="Failed to retrieve service status",
error=f"Status error: {str(e)}"
)
def get_available_models(self) -> Dict[str, Any]:
"""
Get available disaster context models
Returns:
Available models response
"""
try:
available_models = self.service.get_available_models()
model_info = self.service.prediction_model.get_model_info()
return self._create_response(
success=True,
message="Available models retrieved successfully",
data={
'available_disaster_contexts': available_models,
'model_info': model_info,
'default_context': 'Normal',
'supported_forecast_variables': model_info.get('forecast_variables', [])
}
)
except Exception as e:
logger.error(f"WeatherWise models list error: {e}")
return self._create_response(
success=False,
message="Failed to retrieve available models",
error=f"Models error: {str(e)}"
)
def _create_response(self, success: bool, message: str,
data: Dict[str, Any] = None, error: str = None,
processing_info: Dict[str, Any] = None) -> Dict[str, Any]:
"""
Create standardized response dictionary
Args:
success: Success status
message: Response message
data: Response data (optional)
error: Error message (optional)
processing_info: Processing information (optional)
Returns:
Standardized response dictionary
"""
response = {
'success': success,
'message': message,
'timestamp': datetime.now().isoformat(),
'service': 'WeatherWise'
}
if data is not None:
response['data'] = data
if error is not None:
response['error'] = error
if processing_info is not None:
response['processing_info'] = processing_info
return response