ClimApp handles two distinct data paths: an automatic real-time path driven by the user’s GPS coordinates and a manual path where users submit their own measurements. Both paths converge at the same normalization and persistence layer, ensuring that every record stored in the system shares a consistent schema regardless of its origin.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/elenacarino-max/mas-climapp/llms.txt
Use this file to discover all available pages before exploring further.
- Real-Time Weather
- Manual Entry
Browser reads GPS coordinates
The browser loads
index.html. JavaScript immediately calls navigator.geolocation.getCurrentPosition(), prompting the user to allow location access. No data is fetched until the browser has confirmed coordinates.Browser sends coordinates to the API
Once latitude and longitude are available, a JavaScript The page does not reload — the UI updates in place once the response arrives.
fetch call fires:api_controller receives and validates the request
api_controller.py reads the lat and lon query parameters. If either is missing it returns a 400 error immediately. Otherwise it forwards both values to the service layer:api_controller.py
WeatherAPIService sends the first request to AEMET
WeatherAPIService._obtener_datos_crudos() sends a GET request to AEMET’s observation endpoint with the API key in the headers:datos field — a short-lived temporary URL where the actual observation payload is stored.Second request downloads the observation payload
A second
GET is sent immediately to the temporary URL from the previous step. This two-step handshake is how AEMET’s API works; both requests are wrapped in a RetryService session that retries up to three times with exponential back-off on HTTP 429, 500, 502, 503, and 504 errors.Haversine algorithm finds the nearest station
WeatherAPIService.obtener_clima_por_coordenadas() iterates over every observation returned by AEMET. For each station it calls calcular_distancia() from utils/helpers.py, which implements the Haversine formula to compute great-circle distance in kilometres between the user’s coordinates and the station’s coordinates. The observation with the smallest distance is selected.normalizer_service maps raw fields to the standard schema
normalizar_datos_aemet() translates AEMET’s abbreviated field names into the application’s canonical keys:| AEMET field | Standard key | Notes |
|---|---|---|
ubi | ciudad / estacion | Station name |
fint | fecha | Observation timestamp |
ta | temperatura | Air temperature, °C |
hr | humedad | Relative humidity, % |
vv | viento | Wind speed, km/h |
pres | presion | Atmospheric pressure, hPa |
prec | lluvia | Precipitation, mm ("Ip" → 0.0) |
alert_service evaluates thresholds
The normalised dict is passed directly to
AlertService.evaluar_alertas(). The method checks each meteorological variable against its configured thresholds and appends the matching alert codes to a list. The list is then added to the dict under the alertas key. See Alert System for the full threshold table.Record saved to JSONRepository
Back in
api_controller.py, the source tag is added and the record is persisted:api_controller.py
JSONRepository.guardar() appends the dict to data/registros_climaticos.json, creating the file if it does not already exist.