Skip to content

Weather APIs Documentation

Overview

The drone operations management system integrates with three weather forecast APIs to provide reliable, aggregated weather data for flight planning. Weather forecasts are automatically fetched during project creation and cached for 24 hours to optimise API usage while ensuring data freshness.

Purpose in Drone Operations: - Pre-flight weather assessment for safety planning - Risk analysis and viability determination - Compliance with operational weather restrictions - Flight delay/cancellation decision support

Integration Architecture: - Aggregation Strategy: Data from all available sources is averaged for increased reliability - Graceful Degradation: System functions with 1-2 API failures - Caching: 24-hour cache stored in database (Project.weather_forecast JSON column) - Automatic Refetch: Cache validation on project view page


API 1: Open-Meteo (Primary Source)

Service Overview

  • Provider: Open-Meteo.com
  • Cost: Free, no API key required
  • Forecast Range: 16 days
  • Update Frequency: Hourly updates
  • Rate Limits: 10,000 requests/day per IP
  • Data Source: NOAA GFS, ECMWF models

Endpoint

GET https://api.open-meteo.com/v1/forecast

Parameters

Parameter Type Required Description
latitude float Yes WGS84 decimal degrees
longitude float Yes WGS84 decimal degrees
daily string Yes Comma-separated list of daily variables
timezone string No Auto-detect from coordinates (default: 'auto')
start_date string Yes Flight date (YYYY-MM-DD)
end_date string Yes Same as start_date for single-day forecast

Daily Variables Used: - temperature_2m_max - Maximum temperature at 2m (°C) - temperature_2m_min - Minimum temperature at 2m (°C) - temperature_2m_mean - Mean temperature at 2m (°C) - precipitation_sum - Total precipitation (mm) - precipitation_probability_max - Maximum precipitation probability (%) - wind_speed_10m_max - Maximum wind speed at 10m (km/h) - wind_gusts_10m_max - Maximum wind gusts at 10m (km/h) - weather_code - WMO weather code (0-99)

Request Example

import requests

params = {
    'latitude': 55.9533,
    'longitude': -3.1883,
    'daily': 'temperature_2m_max,temperature_2m_min,temperature_2m_mean,precipitation_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,weather_code',
    'timezone': 'auto',
    'start_date': '2025-01-15',
    'end_date': '2025-01-15'
}

response = requests.get('https://api.open-meteo.com/v1/forecast', params=params, timeout=10)
data = response.json()

Response Format

{
  "latitude": 55.95,
  "longitude": -3.19,
  "timezone": "Europe/London",
  "daily": {
    "time": ["2025-01-15"],
    "temperature_2m_max": [12.5],
    "temperature_2m_min": [8.0],
    "temperature_2m_mean": [10.2],
    "precipitation_sum": [2.3],
    "precipitation_probability_max": [45],
    "wind_speed_10m_max": [18.5],
    "wind_gusts_10m_max": [32.0],
    "weather_code": [61]
  }
}

WMO Weather Code Mapping

Code Range Condition
0 Clear
1-3 Partly Cloudy
45, 48 Foggy
51-57 Drizzle
61-67, 80-82 Rain
71-77, 85-86 Snow
95-99 Thunderstorm

Error Handling

  • Timeout: 10-second timeout, returns None on failure
  • HTTP Errors: Logged, returns None
  • Parsing Errors: Invalid/missing fields logged, returns None
  • Rate Limit: 429 response - exponential backoff (not implemented, relies on cache)

API 2: OpenWeatherMap

Service Overview

  • Provider: OpenWeatherMap.org
  • Cost: Free tier available (requires API key)
  • Forecast Range: 5 days (free tier)
  • Update Frequency: Every 3 hours
  • Rate Limits: 60 calls/min, 1,000,000 calls/month (free tier)
  • Data Source: Multiple numerical weather models

Endpoint

GET https://api.openweathermap.org/data/2.5/forecast

Parameters

Parameter Type Required Description
lat float Yes WGS84 decimal degrees
lon float Yes WGS84 decimal degrees
appid string Yes API key from account dashboard
units string Yes Use 'metric' for Celsius/km/h

API Key Setup

  1. Create free account at https://openweathermap.org/api
  2. Navigate to API keys section in dashboard
  3. Generate new API key (activation takes ~2 hours)
  4. Add to .env file:
    OPENWEATHERMAP_API_KEY=your_api_key_here
    

Request Example

import requests
import os

params = {
    'lat': 55.9533,
    'lon': -3.1883,
    'appid': os.getenv('OPENWEATHERMAP_API_KEY'),
    'units': 'metric'
}

response = requests.get('https://api.openweathermap.org/data/2.5/forecast', params=params, timeout=10)
data = response.json()

Response Format

{
  "list": [
    {
      "dt": 1705330800,
      "main": {
        "temp": 10.5,
        "temp_min": 8.2,
        "temp_max": 12.1
      },
      "weather": [
        {
          "main": "Rain",
          "description": "light rain"
        }
      ],
      "wind": {
        "speed": 5.14,
        "gust": 8.23
      },
      "pop": 0.45,
      "rain": {
        "3h": 0.76
      }
    }
    // ... more 3-hour forecasts
  ]
}

Data Aggregation (3-hour to Daily)

The implementation aggregates 3-hour forecasts for the target date: - Temperature Avg: Mean of all 3-hour temps - Temperature Min/Max: Min/max across all 3-hour periods - Precipitation: Sum of all 3-hour rainfall amounts - Precipitation Probability: Maximum probability (conservative) - Wind Speed: Mean of all 3-hour speeds - Wind Gusts: Maximum gust across all periods - Conditions: Most common weather.main value

Error Handling

  • 401 Unauthorized: Invalid API key - skip this source
  • Timeout: 10-second timeout, returns None
  • No Data for Date: If date > 5 days away, returns None
  • Rate Limit: 429 response - skip this source (relies on cache)

API 3: Met Office DataPoint (UK Only)

Service Overview

  • Provider: UK Met Office
  • Cost: Free tier available (requires API key)
  • Forecast Range: 5 days
  • Coverage: UK locations only (49.9-60.9°N, -8.2-1.8°E)
  • Rate Limits: 5,000 requests/day
  • Data Source: UK Met Office numerical models

Geographic Coverage

The implementation automatically checks if coordinates are within UK bounds:

UK_BOUNDS = {
    'lat_min': 49.9,   # Southern UK (Channel Islands)
    'lat_max': 60.9,   # Northern UK (Shetland)
    'lon_min': -8.2,   # Western UK (Ireland)
    'lon_max': 1.8     # Eastern UK
}

Behaviour: - If location outside UK → Met Office API is skipped (not an error) - This prevents wasted API calls for non-UK operations

API Key Setup

  1. Register at https://www.metoffice.gov.uk/services/data/datapoint
  2. Subscribe to "Site Specific Forecast" API
  3. Copy JWT token from API dashboard
  4. Add to .env file:
    MET_OFFICE_API_KEY=your_jwt_token_here
    

Implementation Status

Fully implemented

The Met Office integration is complete and operational: - JWT authentication via apikey header - UK location bounds checking (auto-skips non-UK locations) - 3-hourly forecast aggregation into daily summaries - Weather code mapping (codes 0-30) to human-readable conditions - Automatic unit conversions (m/s to km/h for wind speeds)

Endpoint

GET https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily

Parameters

Parameter Type Required Description
latitude float Yes WGS84 decimal degrees
longitude float Yes WGS84 decimal degrees
excludeParameterMetadata boolean No Set to 'false' to include parameter metadata
includeLocationName boolean No Set to 'true' to include location name in response

Authentication

  • Method: API key header
  • Header: apikey: {your_jwt_token}
  • Token Type: JWT (long-lived bearer token)

Request Example

import requests
import os

params = {
    'latitude': 55.9533,
    'longitude': -3.1883,
    'excludeParameterMetadata': 'false',
    'includeLocationName': 'true'
}

headers = {
    'apikey': os.getenv('MET_OFFICE_API_KEY'),
    'accept': 'application/json'
}

response = requests.get(
    'https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily',
    params=params,
    headers=headers,
    timeout=10
)
data = response.json()

Response Format

Returns GeoJSON FeatureCollection with 3-hourly forecasts:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-3.1883, 55.9533]
      },
      "properties": {
        "location": {
          "name": "Edinburgh"
        },
        "timeSeries": [
          {
            "time": "2025-01-15T00:00Z",
            "maxScreenAirTemp": 12.5,
            "minScreenAirTemp": 8.0,
            "totalPrecipAmount": 0.5,
            "probOfPrecipitation": 45,
            "windSpeed10m": 5.1,
            "max10mWindGust": 8.9,
            "significantWeatherCode": 7
          }
          // ... more 3-hourly entries
        ]
      }
    }
  ]
}

Weather Code Mapping

Code Condition Mapped To
0 Clear night Clear
1 Sunny day Clear
2, 3 Partly cloudy (night/day) Partly Cloudy
5, 6 Mist/Fog Foggy
7, 8 Cloudy/Overcast Cloudy
11 Drizzle Drizzle
9-10, 12-15 Rain showers/Light rain/Heavy rain Rain
16-21 Sleet/Hail (showers) Sleet/Hail
22-27 Snow (light/heavy showers) Snow
28-30 Thunder (showers) Thunderstorm

Full code definitions: https://www.metoffice.gov.uk/services/data/datapoint/code-definitions

Data Aggregation (3-hour to Daily)

The implementation aggregates 3-hourly forecasts for the target date: - Temperature Avg: Mean of all max and min temps - Temperature Min/Max: Min/max across all periods - Precipitation: Sum of all 3-hour amounts (not average) - Precipitation Probability: Maximum probability (conservative) - Wind Speed: Mean of all 3-hour speeds (converted m/s → km/h) - Wind Gusts: Maximum gust across all periods (converted m/s → km/h) - Conditions: Most common weather code (majority vote)


Implementation Notes

Python Integration Example

from app.utils.weather_api import WeatherAPI

# Fetch forecast for Edinburgh
latitude = 55.9533
longitude = -3.1883
flight_date = '2025-01-15'

result = WeatherAPI.get_forecast(latitude, longitude, flight_date)

if result['success']:
    forecast = result['forecast_data']
    metadata = result['metadata']

    print(f"Temperature: {forecast['temperature_avg_c']}°C")
    print(f"Wind: {forecast['wind_speed_kmh']} km/h")
    print(f"Precipitation: {forecast['precipitation_mm']} mm")
    print(f"Sources: {metadata['sources_used']}")
else:
    print(f"Error: {result['error']}")

Coordinate Format

All APIs use WGS84 decimal degrees (GPS standard): - Latitude: -90 to 90 (positive = North) - Longitude: -180 to 180 (positive = East) - Example: Edinburgh = (55.9533, -3.1883)

Date Format

  • Input: ISO 8601 date string (YYYY-MM-DD)
  • Validation: 0-16 days from current date
  • Timezone: All APIs return data in local timezone

Unit Conversions

The implementation handles automatic unit conversions:

Measurement API Units Stored Units Conversion
Temperature °C °C No conversion
Wind Speed m/s (OWM) km/h × 3.6
Wind Speed km/h (Open-Meteo) km/h No conversion
Precipitation mm mm No conversion
Precipitation Probability 0-1 (OWM) 0-100 × 100
Precipitation Probability 0-100 (Open-Meteo) 0-100 No conversion

Timeout Configuration

  • Default: 10 seconds per API call
  • Configurable: Set WeatherAPI.API_TIMEOUT (seconds)
  • Parallel Execution: All 3 APIs called simultaneously (not sequential)
  • Total Max Time: ~10 seconds (parallel execution)

Error Handling Strategy

try:
    weather_data = WeatherAPI.get_forecast(lat, lon, date)

    if weather_data['success']:
        # Use forecast data
        forecast = weather_data['forecast_data']
        sources_used = weather_data['metadata']['sources_used']

        # Check if we got data from multiple sources
        if len(sources_used) >= 2:
            print("High confidence (multiple sources)")
        elif len(sources_used) == 1:
            print("Moderate confidence (single source)")
    else:
        # All APIs failed
        print(f"Weather unavailable: {weather_data['error']}")

except Exception as e:
    # Unexpected error (should never happen in production)
    logger.error(f"Weather API error: {e}")

References

Official Documentation

  • Open-Meteo: https://open-meteo.com/en/docs
  • OpenWeatherMap: https://openweathermap.org/forecast5
  • Met Office: https://www.metoffice.gov.uk/services/data/datapoint

External Resources

  • WMO Weather Codes: https://www.nodc.noaa.gov/archive/arc0021/0002199/1.1/data/0-data/HTML/WMO-CODE/WMO4677.HTM
  • WGS84 Coordinate System: https://en.wikipedia.org/wiki/World_Geodetic_System