# Air Intelligence Backend
Real-time Air Quality Monitoring and Alert Notification System - Backend API Server
- Overview
- Key Features
- Tech Stack
- Getting Started
- Architecture
- API Documentation
- Development Guide
- Deployment
Air Intelligence Backend is a Spring Boot-based RESTful API server that provides real-time air pollution information based on NASA's NO2 air quality data, analyzes risk levels according to user location, and sends web push notifications.
- Real-time Air Quality Data Collection: Automatically fetches NO2 data from external FastAPI server every hour
- AI-Powered PM2.5 Prediction: Integrates with AI prediction service to forecast PM2.5 levels 2 hours ahead
- Pre-calculated Geographic Data & Caching:
- Generate hazardous area polygons using Convex Hull algorithm and store in MongoDB
- Grid-based point data aggregation and storage
- Batch processing to minimize real-time computation load
- Risk Level Analysis: 5-tier warning level system (SAFE, READY, WARNING, DANGER, RUN)
- Point-in-Polygon Algorithm: User location-based hazard zone determination using Ray Casting algorithm
- Web Push Notifications: Automatic alerts when users enter hazardous zones or high PM2.5 is predicted
- User Location Tracking: Store and manage users' last known coordinates
- GeoJSON Format Support: Provide air quality data in standard GeoJSON format
The system integrates with an AI prediction service to provide proactive air quality alerts.
- Scheduled Checking: Every hour, the
WarningSchedulerchecks all user locations - Polygon-Based Risk Assessment: First, determines if users are inside any hazardous warning polygons
- Predictive Analysis: For users outside warning zones, queries the AI prediction API for future PM2.5 levels
- Proactive Notifications: Sends push notifications when predicted PM2.5 exceeds threshold (>0.01) 2 hours ahead
Endpoint: POST https://fastapi.bestbreathe.us/api/predict/pm25
Request Format:
{
"lat": 37.5665,
"lon": 126.9780,
"when": "2025-10-05T14:30:00"
}Response Format:
{
"pred_pm25": 0.0123
}Implementation: NasaDataRepository.findPrediction(lat, lon)
- Automatically calculates prediction time (current time + 2 hours)
- Formats request with ISO 8601 timestamp
- Returns predicted PM2.5 concentration value
- Early Warning: Users receive notifications before air quality deteriorates
- Location-Specific Predictions: Tailored forecasts for each user's exact location
- Complementary to Real-Time Data: Combines current polygon-based warnings with future predictions
- Java 21 - LTS version
- Spring Boot 3.5.6 - Application framework
- Spring Data MongoDB - NoSQL database integration
- Spring Security - Security and CORS configuration
- Spring Validation - Input data validation
- Spring Scheduling - Batch job scheduling
- MongoDB 7.0.24 - Storage for users, air quality data, and GeoFeature data
- Lombok - Reduce boilerplate code
- Web Push (nl.martijndwars) - VAPID-based web push notifications
- BouncyCastle - Cryptography library
- SpringDoc OpenAPI - Automatic API documentation generation
- Gradle 8.x - Build tool
- Docker - Containerization
- JUnit Platform - Testing framework
- Java 21 or higher
- Docker (for running MongoDB)
- Gradle (wrapper included in project)
# Pull and run MongoDB container
docker pull mongodb/mongodb-community-server:7.0.24-rc0-ubi8
docker run --name mongodb -d -p 27017:27017 mongodb/mongodb-community-server:7.0.24-rc0-ubi8# Clone project
git clone <repository-url>
cd AIR_BE
# Build
./gradlew build
# Run application
./gradlew bootRunConfigure the following values in application.yml or as environment variables:
# Web Push VAPID keys (required)
VAPID_PUBLIC_KEY=<your-vapid-public-key>
VAPID_PRIVATE_KEY=<your-vapid-private-key>
# Cookie domain (optional, default: localhost)
COOKIE_DOMAIN=localhost
# CORS allowed origins (optional, default: http://localhost:5173)
CORS_ALLOWED_ORIGINS=http://localhost:5173
# FastAPI server URL (required)
FAST_API_URL=https://fastapi.bestbreathe.usβββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Client βββββββββββ€ Spring Boot API ββββββββββΊβ MongoDB β
β (Browser) β REST β β β β
βββββββββββββββ β - Weather API β β - Users β
β - User API β β - NasaData β
β - Notification β β - GeoFeatures β
ββββββββββββββββββββ βββββββββββββββββββ
β β²
Fetch β β Every 1 hour
NO2 & β β Scheduled
Predictβ β
βΌ β
ββββββββββββββββββββββββββββ
β FastAPI Server β
β - NASA NO2 Data API β
β - AI PM2.5 Prediction β
ββββββββββββββββββββββββββββ
air.intelligence/
βββ config/ # Spring configuration classes
β βββ SpringSecurityConfig.java # CORS, Security settings
β βββ BeanConfig.java # Bean config (RestTemplate, etc.)
β βββ ThirdPartyBeanConfig.java # External library beans (PushService, etc.)
β βββ WarningConstant.java # Warning threshold constants
β
βββ controller/ # REST API endpoints
β βββ WeatherController.java # Air quality data query API
β βββ UserController.java # User management API
β βββ NotificationController.java # Notification subscription API
β
βββ service/ # Business logic
β βββ WeatherService.java # Weather service interface
β βββ DefaultWeatherService.java # Cached GeoFeature data retrieval
β βββ MockDataWeatherService.java # Mock service for testing
β βββ UserService.java # User management service
β βββ NotificationService.java # Push notification service
β βββ NasaDataService.java # NASA data processing
β
βββ repository/ # Data access layer
β βββ UserRepository.java # User MongoDB repository
β βββ WeatherRepository.java # Air quality data MongoDB repository
β βββ GeoFeatureDataRepository.java # GeoFeature cache repository
β βββ NasaDataRepository.java # FastAPI integration (NO2 & AI Prediction)
β βββ dto/ # Repository DTOs
β βββ No2DataDto.java # NO2 data response
β βββ No2ResponseDto.java # NO2 API wrapper
β βββ Pm25PredictionDto.java # AI prediction response (NEW)
β
βββ domain/ # MongoDB entities
β βββ User.java # User domain
β βββ NasaData.java # Air quality data domain
β βββ GeoFeatureData.java # GeoFeature cache domain (NEW)
β
βββ dto/ # API request/response DTOs
β βββ GeoResponse.java # GeoJSON response
β βββ UserCreationDto.java # User creation DTO
β βββ LastCoordUpdateRequest.java # Coordinate update request
β βββ SubscriptionRequest.java # Push subscription request
β
βββ value/ # Value objects
β βββ Coord.java # Coordinates (latitude/longitude)
β βββ WarningLevel.java # Warning level enum
β βββ WarningMessage.java # Warning message
β βββ GeoFeature.java # GeoJSON Feature
β βββ GeoFeatureType.java # GeoJSON type
β βββ GeoProperties.java # GeoJSON Properties
β βββ Geometry.java # GeoJSON Geometry
β
βββ scheduler/ # Scheduled tasks
β βββ WarningScheduler.java # Data collection, GeoFeature generation, notifications
β
βββ error/ # Error handling
β βββ errorcode/ # Error code definitions
β βββ exception/ # Custom exceptions
β βββ handler/ # Global error handlers
β
βββ util/ # Utilities
βββ api/ # API response wrappers
βββ http/ # HTTP utilities
[Execute every 1 hour - fixedRate]
β
βΌ
ββββββββββββββββββββββββββββββββ
β 1. Fetch NO2 data from β
β FastAPI (NasaDataRepo) β
ββββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β 2. Save NasaData to MongoDB β
β (WeatherRepository) β
β - Delete existing data β
ββββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β 3. Calculate & save β
β GeoFeatures β
β (Batch optimization) β
β β
β a) Polygon Features: β
β - Group by warning level β
β - Apply Convex Hull β
β - Save type="polygon" β
β β
β b) Point Features: β
β - Divide into 1Β° grid β
β - Calculate averages β
β - Save type="point" β
ββββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β 4. Determine user risk level β
β (Point-in-Polygon algo) β
β β
β - Query polygon data β
β - Ray Casting algorithm β
β - Check each user locationβ
ββββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β 5. AI Prediction β
β For users NOT in danger β
β β
β - Query PM2.5 prediction β
β API (2 hours ahead) β
β - If pred_pm25 > 0.01: β
β Send notification β
ββββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ
β 6. Send web push β
β notifications for β
β DANGER+ levels β
ββββββββββββββββββββββββββββββββ
Polygon Endpoint (/api/v1/weathers/polygon)
[Client Request]
β
βΌ
βββββββββββββββββββββββββββββββ
β 1. Query type="polygon" β
β from GeoFeatureDataRepo β
β (pre-calculated data) β
βββββββββββββ¬ββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββ
β 2. Return cached GeoJSON β
β Polygon immediately β
β (no real-time calc) β
βββββββββββββββββββββββββββββββ
Point Endpoint (/api/v1/weathers/point)
[Client Request]
β
βΌ
βββββββββββββββββββββββββββββββ
β 1. Query type="point" β
β from GeoFeatureDataRepo β
β (pre-calculated data) β
βββββββββββββ¬ββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββ
β 2. Return cached GeoJSON β
β Point immediately β
β (no real-time calc) β
βββββββββββββββββββββββββββββββ
Previous Architecture:
- Real-time Convex Hull calculation for every API request
- MongoDB queries and complex algorithms executed per request
- High response latency and server load
Improved Architecture:
- β Pre-calculation: Scheduler calculates GeoFeatures every 5 minutes
- β
Caching Strategy: Store in
GeoFeatureDatacollection (separated by type) - β Fast Response: APIs only perform simple queries
- β Consistency: All clients retrieve identical data
Performance Improvements:
- API response time: ~500ms β ~10ms (approximately 50x improvement)
- Reduced server CPU usage
- Improved concurrent user handling capacity
Uses Ray Casting Algorithm for user location-based risk level determination:
// WarningScheduler.java - isPointInPolygon()
- Cast a ray to the right from user coordinates (lon, lat)
- Count intersections with each polygon edge
- Odd number of intersections: inside (inside = true)
- Even number of intersections: outside (inside = false)| Level | NO2 Range | Description | Notification |
|---|---|---|---|
| SAFE | < 2.0 | Safe | β |
| READY | 2.0 ~ 4.0 | Caution | β Push notification |
| WARNING | 4.0 ~ 6.0 | Warning | β Push notification |
| DANGER | 6.0 ~ 7.8 | Dangerous | β Push notification |
| RUN | β₯ 7.8 | Very dangerous | β Push notification |
Warning thresholds are managed in WarningConstant.java.
After running the application, access the auto-generated API documentation via SpringDoc OpenAPI:
http://localhost:8080/swagger-ui/index.html
-
GET /api/v1/weathers/polygon- Query polygon data by warning level- Response: GeoJSON FeatureCollection (Polygon)
- Returns pre-calculated cached data
-
GET /api/v1/weathers/point- Query grid-based point data- Response: GeoJSON FeatureCollection (Point)
- Returns pre-calculated cached data
POST /api/v1/users- Create userGET /api/v1/users/{userId}- Get userPUT /api/v1/users/{userId}/coord- Update user location
POST /api/v1/notifications/subscribe- Subscribe to push notifications
- Use Lombok annotations (
@RequiredArgsConstructor,@Getter,@Builder, etc.) - Use constructor injection pattern
- Interface-based service design (swappable implementations)
| Collection | Purpose | Key Fields |
|---|---|---|
users |
User information | id, lastCoord, pushSubscription, warningLevel |
nasaData |
Raw NO2 data | timestamp, kind, lat, lon, value |
geo_feature |
GeoFeature cache | timestamp, type (polygon/point), features[] |
@Scheduled(fixedRate = 1000 * 60 * 60) // Every 1 hour
public void task() {
1. Fetch NO2 data
2. Save NasaData
3. Calculate and save GeoFeatureData (polygon, point)
4. Determine user risk levels (Point-in-Polygon)
5. Determine predicted (by AI) user risk levels
6. Send push notifications
}# 1. Build application
./gradlew build
# 2. Copy jar file from build/libs/ to build/docker/
mkdir -p build/docker
cp build/libs/*.jar build/docker/app.jar
# 3. Build Docker image
docker build -t air-intelligence .
# 4. Run Docker container
docker run -d \
-p 8080:8080 \
-e VAPID_PUBLIC_KEY=<your-key> \
-e VAPID_PRIVATE_KEY=<your-key> \
-e FAST_API_URL=https://fastapi.bestbreathe.us \
-e CORS_ALLOWED_ORIGINS=https://your-domain.com \
--name air-intelligence-app \
air-intelligence