165 lines
4.7 KiB
Markdown
165 lines
4.7 KiB
Markdown
# Weather Alerts - Implementation Roadmap
|
|
|
|
## Overview
|
|
This document captures the implementation plan and decisions for the weather alerts application.
|
|
|
|
## Architecture
|
|
|
|
### Directory Structure
|
|
```
|
|
weather_alerts/
|
|
├── app/
|
|
│ ├── __init__.py
|
|
│ ├── main.py # Entry point - orchestration
|
|
│ ├── config/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── loader.py # Typed YAML config loader
|
|
│ │ ├── settings.yaml # Main configuration
|
|
│ │ └── settings.example.yaml # Example (no secrets)
|
|
│ ├── models/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── weather.py # Weather data models
|
|
│ │ ├── alerts.py # Alert rule/triggered alert models
|
|
│ │ └── state.py # Deduplication state models
|
|
│ ├── services/
|
|
│ │ ├── __init__.py
|
|
│ │ ├── weather_service.py # VisualCrossing API client
|
|
│ │ ├── notification_service.py # ntfy sender
|
|
│ │ ├── rule_engine.py # Alert rule evaluation
|
|
│ │ └── state_manager.py # Deduplication persistence
|
|
│ └── utils/
|
|
│ ├── __init__.py
|
|
│ ├── http_client.py # Centralized HTTP wrapper
|
|
│ └── logging_config.py # Structlog setup
|
|
├── tests/
|
|
├── data/ # State files (gitignored)
|
|
├── .env.example
|
|
├── .gitignore
|
|
├── requirements.txt
|
|
└── run.py # Simple runner
|
|
```
|
|
|
|
## Key Design Decisions
|
|
|
|
### 1. One-Shot Execution
|
|
The application is designed for cron-based scheduling rather than internal scheduling. Each run:
|
|
1. Fetches current forecast
|
|
2. Evaluates rules
|
|
3. Sends new alerts
|
|
4. Exits
|
|
|
|
### 2. Secrets Management
|
|
- API keys and tokens stored in environment variables only
|
|
- `.env` file for local development (gitignored)
|
|
- No secrets in YAML configuration
|
|
|
|
### 3. Atomic State Persistence
|
|
State file writes use write-to-temp-then-rename pattern for crash safety:
|
|
```python
|
|
fd, temp_path = tempfile.mkstemp(...)
|
|
# Write to temp file
|
|
os.replace(temp_path, actual_path) # Atomic rename
|
|
```
|
|
|
|
### 4. Deduplication Strategy
|
|
Alerts are deduplicated using the key format: `{alert_type}:{forecast_hour}`
|
|
|
|
This allows:
|
|
- Re-alerting for different forecast hours
|
|
- Preventing duplicate alerts for the same condition/hour
|
|
- Configurable deduplication window (default 24 hours)
|
|
|
|
### 5. Typed Throughout
|
|
- Dataclasses for all data models
|
|
- Type hints on all functions
|
|
- Configuration loaded into typed dataclasses
|
|
|
|
### 6. Centralized HTTP
|
|
Single `HttpClient` wrapper provides:
|
|
- Consistent timeouts
|
|
- Automatic retries with exponential backoff
|
|
- Structured logging
|
|
- Shared across services
|
|
|
|
## Alert Rules
|
|
|
|
### Temperature
|
|
- **Low temperature**: Alert when forecast drops below threshold (default: 32°F)
|
|
- **High temperature**: Alert when forecast exceeds threshold (default: 100°F)
|
|
|
|
### Precipitation
|
|
- Alert when precipitation probability exceeds threshold (default: 70%)
|
|
|
|
### Wind
|
|
- **Sustained wind**: Alert when speed exceeds threshold (default: 25 mph)
|
|
- **Wind gusts**: Alert when gusts exceed threshold (default: 40 mph)
|
|
|
|
### Severe Weather
|
|
- Forwards any severe weather alerts from the VisualCrossing API
|
|
|
|
## Execution Flow
|
|
|
|
```
|
|
1. Load configuration (YAML + environment)
|
|
2. Configure logging (structlog)
|
|
3. Initialize services
|
|
4. Fetch weather forecast
|
|
5. Evaluate alert rules
|
|
6. Filter duplicate alerts
|
|
7. Send new alerts via ntfy
|
|
8. Record sent alerts
|
|
9. Purge old records
|
|
10. Save state
|
|
11. Exit (0=success, 1=error)
|
|
```
|
|
|
|
## Dependencies
|
|
|
|
| Package | Purpose |
|
|
|---------|---------|
|
|
| requests | HTTP client |
|
|
| structlog | Structured logging |
|
|
| python-dotenv | Environment variable loading |
|
|
| PyYAML | Configuration parsing |
|
|
| pytest | Testing |
|
|
| responses | HTTP mocking for tests |
|
|
|
|
## Testing
|
|
|
|
Run tests with:
|
|
```bash
|
|
pytest tests/ -v
|
|
```
|
|
|
|
Test coverage:
|
|
- Rule engine: Temperature, precipitation, wind, severe weather rules
|
|
- Weather service: API parsing, error handling
|
|
- State manager: Persistence, deduplication, purging
|
|
|
|
## Usage
|
|
|
|
### Setup
|
|
1. Copy `.env.example` to `.env` and fill in API keys
|
|
2. Copy `app/config/settings.example.yaml` to `app/config/settings.yaml` (optional customization)
|
|
3. Install dependencies: `pip install -r requirements.txt`
|
|
|
|
### Running
|
|
```bash
|
|
python run.py
|
|
```
|
|
|
|
### Cron Integration
|
|
Add to crontab for hourly checks:
|
|
```cron
|
|
0 * * * * cd /path/to/weather_alerts && /path/to/python run.py >> /var/log/weather-alerts.log 2>&1
|
|
```
|
|
|
|
## Future Enhancements
|
|
|
|
Potential additions if needed:
|
|
- Additional alert types (UV index, humidity, etc.)
|
|
- Multiple location support
|
|
- Alert cooldown periods
|
|
- Notification channels beyond ntfy
|
|
- Web dashboard for status
|