Skip to content

breathe-OSS/api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

91 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Breathe backend

A modular FastAPI backend designed to retrieve and standardize air quality data across the Jammu & Kashmir region for the BreatheOSS clients. The system aggregates data from multiple providers: OpenMeteo for satellite-based estimates and AirGradient for high-precision ground sensors. It currently calculates AQI based on both Indian (CPCB) and US EPA standards.

How the AQI is Calculated

[1] The system accepts a dictionary of raw pollutant values. Before any math occurs, the system sanitizes the input keys using a robust mapping strategy.

  • It handles variations in naming conventions (e.g., mapping "pm2.5", "pm25", or "pm2_5" all to the internal standard pm2_5).

  • This ensures that no data is dropped due to typo-sensitivity or API inconsistencies.

[2] The system calculates AQI using two major standards: Indian (CPCB) and US EPA. Each has specific unit requirements:

  • Indian AQI: PM2.5, PM10, NO2, SO2 are maintained in µg/m³. Carbon Monoxide (CO) and Methane (CH4) are divided by 1000 to convert from µg/m³ to mg/m³.

  • US EPA AQI: Gases (NO2, SO2, CO) are converted from µg/m³ to parts-per-billion (ppb) or parts-per-million (ppm) based on molar volume at 25°C.

  • Methane (CH4) is tracked but currently not included in AQI calculations for either standard.

[3] Once units are standardized, the system calculates an individual Sub-Index for each pollutant using Linear Interpolation.

  • The system scans the AQI_BREAKPOINTS (Indian) or US_BREAKPOINTS configuration to find the specific range [Clo​,Chi​] that the current concentration falls into.

  • The system applies the standard AQI formula:

    I=[(Chi​−Clo​)(Ihi​−Ilo​)​×(C−Clo​)]+Ilo​

Where:

  • I: The calculated AQI sub-index.
  • C: The current pollutant concentration.
  • Clo​/Chi​: The concentration breakpoints (lower and upper bounds).
  • Ilo​/Ihi​: The corresponding AQI index breakpoints.

The code includes failsafes: if a value exceeds the maximum defined breakpoint, it is capped at 500; if it is below the minimum, it defaults to 0.

[4] The final Air Quality Index is not an average of the pollutants.

  • The system identifies the maximum value among all calculated sub-indices.
  • The pollutant responsible for this highest value is flagged as the main_pollutant.
  • Both the Indian aqi and the us_aqi are calculated and returned in the final payload.

Structure

api/
├── main.py                     # Entry point
├── Procfile
├── requirements.txt
├── .env
├── breathe.db                  # Local SQLite database (auto-generated)
└── app/
    ├── __init__.py
    ├── api/                    # Routes & endpoints
    │   ├── __init__.py
    │   └── routes.py
    ├── core/                   # Config, database, conversions
    │   ├── __init__.py
    │   ├── config.py
    │   ├── database.py
    │   └── conversions.py
    ├── data/                   # Static JSON data files
    │   ├── __init__.py
    │   ├── zones.json
    │   ├── nodes.json          # AirGradient node configurations
    │   ├── sensor_info.json    # Hardware sensor metadata
    │   └── aqi_breakpoints.json
    └── services/               # Data fetching & processing
        ├── __init__.py
        └── fetchers.py

Main modules

  • main.py Initializes the FastAPI application and starts a background scheduler. This scheduler runs every 15 minutes to fetch fresh data for all zones, ensuring the app serves cached data instantly without hitting API rate limits during user requests.
  • app/api/routes.py Generates all /aqi/<zone_id> endpoints dynamically based on zones.json.
  • app/core/database.py Handles data persistence using PostgreSQL (production) or SQLite (local development). Stores sensor readings, temperature, and humidity for historical graph plotting.
  • app/core/config.py Loads environment variables and configuration from zones.json, nodes.json, and aqi_breakpoints.json.
  • app/core/conversions.py Handles the mathematics of AQI calculation, unit conversions (e.g., CO from µg/m³ to mg/m³), and Indian CPCB sub-index mapping along with US EPA sub-index mapping.
  • app/services/fetchers.py Contains sophisticated data fetching logic:
    • fetch_openmeteo_live: Queries satellite-based pollutant data.
    • fetch_multi_node_airgradient: Averages data from multiple AirGradient nodes (e.g., Jammu and Srinagar), with built-in spike detection, grace periods for erratic nodes, and stale data protection.
    • get_zone_data: Implements a multi-layered caching strategy. It prioritize ground sensors but automatically falls back to satellite data if physical sensors are offline or reporting unrealistic spikes.
  • app/data/zones.json Contains zone definitions including names, coordinates, and zone_type (hills, urban, industrial) for customized AQI calculation.
  • app/data/nodes.json Maps specific physical sensor locations (location_id) to city-level zones.
  • app/data/sensor_info.json Stores hardware-specific metadata for ground sensors (model, coordinates, installation dates).
  • app/data/aqi_breakpoints.json Official Indian AQI breakpoint tables.

Requirements

  • python ≥ 3.10
  • fastapi
  • httpx
  • python-dotenv
  • uvicorn
  • psycopg2-binary (for Postgres support)

Environment Variables

AIRGRADIENT_TOKEN=yourkeyhere
JAMMU_AIRGRADIENT_TOKEN=yourkeyhere
DATABASE_URL=postgres://... (optional, defaults to local sqlite)

Running

From the api directory: uvicorn main:app --reload

Endpoints

  • Zone Data: Access data for a specific zone using its dynamic ID (e.g., srinagar, jammu_city, leh): GET /aqi/<zone_id>

  • Generic Lookup: GET /aqi/zone/{zone_id}

  • List All Zones: GET /zones

  • Hardware Sensor Metadata: GET /sensor-info

Development

The project is designed to be data-driven. Adding a new town or district does not require changing Python code; you simply add a new entry to zones.json. Similarly, if government standards change, updating aqi_breakpoints.json will instantly update the calculation logic across the entire application.

About

Breathe App backend

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors