A small Python service that checks a short-range rain forecast every 5 minutes and sends a push notification to your phone roughly 30–60 minutes before rain is expected, so you have time to cover or move your plants.
It has no external Python dependencies and costs nothing for personal use.
every 5 min forecast API ntfy.sh
┌──────────┐ GET ┌──────────────────┐ rain? ┌────────────┐ push ┌─────────┐
│ cron / │ ──────► │ Open-Meteo or │ ────────► │ alert if │ ───────► │ phone │
│ Lambda │ │ OpenWeatherMap │ │ not in │ │ │
└──────────┘ └──────────────────┘ │ cooldown │ └─────────┘
└────────────┘
- The script fetches the precipitation forecast for your location.
- It looks for the first time slot within the lookahead window where rain meets the threshold.
- If rain is found and no alert has been sent in the last few hours, it posts a message to your ntfy topic.
- It records the alert time so a long storm doesn't send repeated notifications.
| File | Purpose |
|---|---|
rain_alert.py |
Local server version using Open-Meteo (15-minute data). Best for North America and Central Europe. |
rain_alert_owm.py |
Local server version using OpenWeatherMap (minute-by-minute data for the next hour). Better for other regions, such as Brazil. |
rain-alert.env |
Settings for rain_alert.py. |
rain-alert-owm.env |
Settings for rain_alert_owm.py, tuned for tropical regions. |
lambda_function.py |
AWS Lambda version (Open-Meteo), storing state in SSM Parameter Store. |
template.yaml |
AWS SAM template: function, 5-minute schedule, and IAM permissions. |
| Region | Recommended script | Why |
|---|---|---|
| USA, Canada | rain_alert.py |
Open-Meteo uses NOAA's HRRR model, which provides true 15-minute forecasts. |
| Central Europe | rain_alert.py |
Open-Meteo uses Germany's ICON-D2 high-resolution model. |
| Brazil, India, Africa, rest of the world | rain_alert_owm.py |
Open-Meteo's 15-minute values are interpolated from hourly global models there; OpenWeatherMap offers a minute-by-minute forecast. |
Accuracy caveat: No forecast is perfect at a 30-minute range. Large rain bands are predicted well. Sudden afternoon thunderstorms, common in summer and in the tropics, can form in 15–30 minutes and are sometimes missed. For plants, a false alarm is cheap and a miss is costly, so the defaults lean slightly toward alerting.
-
Install the free ntfy app from the Play Store or App Store. No account is needed.
-
Tap + and subscribe to a topic name that is hard to guess, for example
garden-rain-8x3k2q. Anyone who knows the topic name can read or send messages to it, so keep it obscure. -
Test it from any computer:
curl -d "Test from my garden server" ntfy.sh/garden-rain-8x3k2qIf a notification appears on your phone, notifications are working.
Android tip: Disable battery optimization for the ntfy app, or notifications may arrive late.
Requires Python 3 and a machine that stays on 24/7.
-
Copy the script and its env file into a folder, for example
~/rain-alert/. -
Edit the env file with your settings (see Configuration).
-
Test it once:
cd ~/rain-alert set -a && . ./rain-alert.env && set +a python3 rain_alert.py
You should see output such as
{"rain": false}. -
Schedule it every 5 minutes with
crontab -e:*/5 * * * * cd $HOME/rain-alert && set -a && . ./rain-alert.env && set +a && /usr/bin/python3 rain_alert.py >> log.txt 2>&1
For the OpenWeatherMap version, replace
rain-alert.envwithrain-alert-owm.envandrain_alert.pywithrain_alert_owm.py.
Windows: Use Task Scheduler with a task that repeats every 5 minutes, setting the environment variables in a small .bat wrapper.
Requires the AWS SAM CLI and an AWS account.
-
Put
lambda_function.pyandtemplate.yamlin one folder. -
Build and deploy:
sam build && sam deploy --guided -
Enter
Lat,Lon, andNtfyTopicwhen prompted. -
To test notifications, run the function once with
LOOKAHEAD_MIN=1440andMIN_PRECIP_MM=0, confirm the alert arrives, then remove those overrides and delete the/rain-alert/lastSSM parameter so the cooldown doesn't block the next real alert.
The Lambda version currently uses Open-Meteo. To use OpenWeatherMap on Lambda, copy get_forecast() from rain_alert_owm.py into lambda_function.py and add OWM_API_KEY to the template's environment variables.
- Create an account at openweathermap.org.
- Subscribe to "One Call by Call" (One Call API 3.0). It includes 1,000 free calls per day. A credit card is required during activation, but you are only charged if you exceed the free tier.
- Cap your usage at 1,000 calls per day in the Billing plans tab. The default limit is 2,000, so lowering it guarantees you never pay.
- A new key can take up to 2 hours to activate. Authentication errors in the first hour are normal.
Checking every 5 minutes uses about 288 calls per day, well within the free limit.
All settings are environment variables in the .env file.
| Variable | Required | Default | Description |
|---|---|---|---|
LAT, LON |
Yes | — | Your garden's coordinates. Long-press the spot in Google Maps to get them. |
NTFY_TOPIC |
Yes | — | Your ntfy topic name. |
LOCATION_NAME |
No | lat/lon | Human-readable place name included in the alert message (for example New York City, NY). |
OWM_API_KEY |
OWM only | — | OpenWeatherMap API key. |
LOOKAHEAD_MIN |
No | 45 |
How many minutes ahead to look for rain. Maximum 60 for OpenWeatherMap. |
MIN_PRECIP_MM |
No | 0.1 (Open-Meteo), 0.3 (OWM) |
Rain threshold. Open-Meteo: mm per 15-minute slot. OpenWeatherMap: intensity in mm/h. |
COOLDOWN_HOURS |
No | 3 |
Minimum time between alerts. |
STATE_FILE |
No | ~/.rain-alert-last |
Where the last alert time is stored (local versions). |
- Missing some showers? Lower
MIN_PRECIP_MM(for example 0.05 for Open-Meteo, or 0.1 mm/h for OpenWeatherMap) or increaseLOOKAHEAD_MIN. - Too many false alarms? Raise
MIN_PRECIP_MM. - Tropical climate? Use
LOOKAHEAD_MIN=60to catch fast-forming afternoon storms. - Review
log.txt(or CloudWatch logs on Lambda) after a couple of weeks and compare alerts with actual rain.
| Item | Local server | AWS Lambda |
|---|---|---|
| Weather data | Free | Free |
| Notifications (ntfy.sh) | Free | Free |
| Compute | Electricity only (about $5/year for a Raspberry Pi) | $0 within the AWS free tier |
| Hardware | $0 if you have a server; about $50–80 once for a Raspberry Pi | None |
If you offer this as a product or service:
- Open-Meteo is free only for non-commercial use. Its commercial Standard plan is about $29/month for 1 million calls, which covers roughly 115 locations at 5-minute polling (or 230–350 locations at 10–15-minute polling).
- OpenWeatherMap charges per call beyond 1,000 calls/day.
- ntfy.sh offers paid plans for higher volume, or you can self-host ntfy for free.
- The current scripts handle one location per copy. Serving many users requires a backend that stores each user's location and notification topic.
Check each provider's pricing page before launching, as prices can change.
| Problem | Likely cause and fix |
|---|---|
| No notification when testing | Check the topic name matches exactly in the app and env file. Test with curl first. |
| Notifications arrive late (Android) | Disable battery optimization for the ntfy app. |
401 Unauthorized from OpenWeatherMap |
The key is still activating (wait up to 2 hours), or the One Call subscription isn't enabled. |
429 Too Many Requests |
You hit the daily call limit. Check your polling interval and billing cap. |
| Script runs but never alerts | Check log.txt. If it shows "reason": "cooldown", an alert was already sent recently. Delete the state file to reset. |
| Cron job doesn't run | Use absolute paths, and check log.txt for errors such as missing environment variables. |
- Rain sensor: Wire a cheap rain sensor to a Raspberry Pi to alert the moment rain actually starts, as a backup when the forecast misses a sudden storm.
- Automatic cover: Use the same trigger to drive a motor or relay that closes a cover or awning over the plants.
- Self-hosted ntfy: Run your own ntfy server for private topics with access control.
- Multi-user service: Store multiple locations and topics, and loop over them in one scheduled run.