Rust + Tauri implementation of the JMA Weather Warning Checker.
PRODUCTION READY
All features have been implemented and tested. This application is feature-complete and production-ready.
- Database layer (SQLite with sqlx, async)
- Configuration management (environment variables, .env support)
- Email notifications (Gmail SMTP with rustls)
- Scheduler (10-minute weather checks, daily cleanup at 01:00)
- Error handling (custom error types with thiserror)
- Data cleanup (old records removal, soft delete, XML file movement)
- JMA XML Parser - Complete implementation:
- extra.xml parsing (Atom feed, If-Modified-Since)
- VPWW54 format parsing (full-width character support)
- City-level warning extraction
- "No warnings" status handling (発表警報・注意報はなし)
- Weather Checker - Complete implementation:
- Status change detection
- XML file change detection (updates DB without notification)
- Database integration
- Notification triggering
- LMO cleanup when no entry in extra.xml
- Resilience - Two-layer architecture (code-level + OS-level):
- Enhanced logging (elapsed time, consecutive failure counter)
- Heartbeat file for external monitoring
- Startup notification email
- Graceful shutdown (SIGTERM/SIGINT handling)
- Crash recovery with OS-level auto-restart
- Deployment - Service configurations for multiple platforms:
- systemd (Ubuntu), launchd (macOS), NSSM (Windows)
This is a background service application that runs continuously:
Tauri App (Background Service)
├── Scheduler (tokio-cron-scheduler)
│ ├── Weather check: Every 10 minutes
│ ├── Cleanup: Daily at 01:00
│ ├── Heartbeat file (data/heartbeat)
│ └── Startup notification email
├── Database (SQLite via sqlx)
│ ├── Extra (Last-Modified tracking)
│ ├── VPWW54xml (XML file cache)
│ └── CityReport (Warning state)
├── JMA Feed Client
│ ├── Fetch extra.xml with If-Modified-Since
│ ├── Parse VPWW54 entries
│ ├── Download and cache warning data
│ └── Handle "no warnings" status
├── Weather Checker
│ ├── Compare and detect changes
│ ├── Track XML file changes
│ └── Clean up old data
├── Notification (Gmail SMTP)
│ ├── Send email on warning status change
│ └── Send system notification (startup, etc.)
└── Resilience
├── Graceful shutdown (SIGTERM/SIGINT via CancellationToken)
├── Crash recovery monitor (exit(1) for OS-level restart)
└── Enhanced logging (elapsed time, failure counter)
- Rust 1.70+ (tested with 1.91.1)
- System dependencies (for Tauri):
- Linux:
libwebkit2gtk-4.1-dev,build-essential,curl,wget,file,libssl-dev,libgtk-3-dev,librsvg2-dev - macOS: Xcode Command Line Tools
- Windows: Microsoft Visual Studio C++ Build Tools
- Linux:
sudo apt update
sudo apt install libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
file \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-devcp .env.example .env
# Edit .env and add your Gmail credentialsRequired environment variables:
GMAIL_APP_PASS=your_gmail_app_password
GMAIL_FROM=your_email@gmail.com
EMAIL_TO=recipient@example.com
EMAIL_BCC=bcc@example.com # OptionalDevelopment mode (with debug logs):
cd src-tauri
RUST_LOG=tauri_weather_checker=debug cargo runProduction mode:
cd src-tauri
cargo build --release
./target/release/tauri-weather-checkercd src-tauri
# With detailed logging
RUST_LOG=tauri_weather_checker=debug cargo run
# With standard logging
cargo runWhat happens:
- Initializes SQLite database
- Runs initial weather check
- Schedules checks every 10 minutes
- Schedules cleanup daily at 01:00
- Continues running indefinitely
Stop with: Ctrl+C
cd src-tauri
# Build release binary (first time only)
cargo build --release
# Run the binary
./target/release/tauri-weather-checker
# Or with logging
RUST_LOG=tauri_weather_checker=info ./target/release/tauri-weather-checkerFor production use, run as a system service with automatic restart and monitoring.
Service configuration files for systemd (Ubuntu), launchd (macOS), and NSSM (Windows) are provided in the deploy/ directory.
See deploy/README.md for detailed setup instructions.
All configuration is done via environment variables (.env file):
| Variable | Description | Default | Required |
|---|---|---|---|
CONFIG_PATH |
Path to config.yaml | config.yaml |
No |
DATADIR |
XML cache directory | data/xml |
No |
DELETED_DIR |
Deleted XML directory | data/deleted |
No |
DB_PATH |
SQLite database path | data/weather.sqlite3 |
No |
GMAIL_APP_PASS |
Gmail app password | - | Yes |
GMAIL_FROM |
Sender email | - | Yes |
EMAIL_TO |
Recipient email | - | Yes |
EMAIL_BCC |
BCC email (comment out to disable) | - | No |
- Enable 2-factor authentication in Google Account
- Generate an app password: https://myaccount.google.com/apppasswords
- Use the app password (not your regular password) in
GMAIL_APP_PASS
Monitored regions are configured in config.yaml:
monitored_regions:
- lmo: "静岡地方気象台"
cities:
- name: "裾野市"
url: "https://www.jma.go.jp/bosai/warning/#lang=ja&area_type=class20s&area_code=2222000"
- name: "御殿場市"
url: "https://www.jma.go.jp/bosai/warning/#lang=ja&area_type=class20s&area_code=2221500"
- lmo: "金沢地方気象台"
cities:
- name: "能登町"Each city entry has the following fields:
| Field | Description | Required |
|---|---|---|
name |
City name as it appears in JMA warnings | Yes |
url |
JMA warning page URL for this city | No |
url is optional. If omitted, the notification email will link to the JMA national warnings page (https://www.jma.go.jp/bosai/warning/). The city-specific URL can be found at JMA Warning Page by navigating to the target city and copying the URL from the browser address bar.
Set the config file path in .env:
CONFIG_PATH=../config.yaml
After modifying config.yaml, changes take effect on the next 10-minute check cycle (no restart or rebuild required).
weather-warning-checker/
├── src-tauri/
│ ├── src/
│ │ ├── main.rs # Entry point, Tauri setup
│ │ ├── config.rs # Environment and YAML configuration
│ │ ├── database.rs # SQLite operations
│ │ ├── jma_feed.rs # JMA XML fetching/parsing
│ │ ├── weather_checker.rs # Core warning logic
│ │ ├── notification.rs # Email notifications (test mode support)
│ │ ├── cleanup.rs # Data cleanup tasks
│ │ ├── scheduler.rs # Cron-like scheduling
│ │ └── error.rs # Error types
│ ├── Cargo.toml # Rust dependencies
│ ├── tauri.conf.json # Tauri configuration
│ └── data/ # Auto-created (runtime data)
│ ├── xml/ # XML cache
│ ├── deleted/ # Deleted XML files
│ └── weather.sqlite3 # Database
├── deploy/
│ ├── systemd/ # Ubuntu service files
│ │ ├── weather-checker.service
│ │ ├── weather-checker-watchdog.service
│ │ └── weather-checker-watchdog.timer
│ ├── launchd/ # macOS plist
│ │ └── com.aktnk.weather-checker.plist
│ ├── windows/ # Windows NSSM scripts
│ │ ├── install.ps1
│ │ └── uninstall.ps1
│ └── README.md # Deployment guide
├── config.yaml # Monitored regions configuration
├── .env # Environment configuration
├── .env.example # Example environment file
└── README.md # This file
The application uses SQLite with the following tables:
- extra: Tracks Last-Modified header from JMA
- vpww54xml: Records all downloaded XML files
- city_report: Tracks current warning status for each city+warning combination
Database location: data/weather.sqlite3
To inspect:
sqlite3 data/weather.sqlite3
.tables
SELECT * FROM city_report WHERE is_delete = 0;
.quitLog levels: error, warn, info, debug, trace
# Minimal logs (info and above)
RUST_LOG=tauri_weather_checker=info cargo run
# Debug logs (recommended for development/testing)
# Note: Email subjects are prefixed with "test:" in debug mode
RUST_LOG=tauri_weather_checker=debug cargo run
# All logs (very verbose)
RUST_LOG=tauri_weather_checker=trace cargo runWhen RUST_LOG contains "debug", email subjects are automatically prefixed with "test:":
- Debug mode:
test:裾野市:大雨警報:発表 - Production mode:
裾野市:大雨警報:発表
# Delete database to reinitialize
rm -f data/weather.sqlite3
cargo run- Verify
.envfile exists with correct credentials - Check Gmail app password (not regular password)
- Ensure 2FA is enabled on Google account
- Review logs:
RUST_LOG=tauri_weather_checker=debug cargo run
# Update Rust
rustup update
# Clean build
cd src-tauri
cargo clean
cargo build# Check Rust version (1.70+ required)
rustc --version
# Update dependencies
cargo updateWhen making changes:
- Format code:
cargo fmt - Run linter:
cargo clippy - Check compilation:
cargo check - Test:
cargo run - Build release:
cargo build --release
Future improvements:
- System tray menu (icons needed)
- GUI configuration interface
- Log file rotation
- Auto-update mechanism
MIT License