I got a Seestar S50 — ZWO’s little smart telescope — about a year ago. The hardware is excellent: point it at anything, tap the app, watch the stacking happen live. But there’s an unavoidable problem with amateur astronomy in London: the weather.

M31 Andromeda Galaxy captured with Seestar S50

M31 — the Andromeda Galaxy, our nearest large neighbour at 2.5 million light-years. Seestar S50, 46 minutes integration, July 2025. Dust lanes visible along the disc; M32 satellite galaxy upper right.

Most nights are either cloudy, hazy, or just marginal. And the worst outcome is dragging the telescope out, setting it up, waiting for alignment — and then clouds roll in. So I built a simple automated alert that tells me, every evening at 5pm, whether tonight is actually worth setting up.

The Idea

Every day at 17:00, a cron job checks the weather forecast for astronomical darkness in London. If the sky is clear — cloud cover under 20%, no rain, visibility over 15km — I get a Telegram notification. If not, silence. No noise, no false alarms.

The key insight: don’t notify me about bad nights. Only alert me when conditions are good.

Calculating Astronomical Night

“Dark enough for astronomy” isn’t the same as “after sunset.” I needed astronomical twilight — when the sun is 18° below the horizon and the sky is truly dark. For that, I used the excellent astral Python library:

from astral import LocationInfo
from astral.sun import dusk, dawn

CITY = LocationInfo("London", "England", "Europe/London", 51.5074, -0.1278)

# Astronomical dusk (sun 18° below horizon)
obs_start = dusk(CITY.observer, date=today, depression=18, tzinfo=tz)

# Astronomical dawn next morning
obs_end = dawn(CITY.observer, date=tomorrow, depression=18, tzinfo=tz)

This gives me the exact observation window for tonight — which in London ranges from around 22:30–03:30 in winter to (ironically) never getting fully dark in midsummer.

I handle the polar summer edge case too: if dusk() raises an exception (no astronomical twilight), fall back to a late-night window.

Weather Data from Open-Meteo

I use Open-Meteo — free, no API key needed, excellent hourly forecasts. I fetch cloud cover, precipitation, visibility, and weather code for the next two days:

url = (
    f"https://api.open-meteo.com/v1/forecast"
    f"?latitude=51.5074&longitude=-0.1278"
    f"&hourly=cloud_cover,precipitation,visibility,weather_code"
    f"&timezone=Europe%2FLondon"
    f"&forecast_days=2"
)

Then I filter to only the hours within the astronomical window and evaluate each one against thresholds:

  • Cloud cover: ≤ 20%
  • Precipitation: ≤ 0.1 mm/h
  • Visibility: ≥ 15 km
bad_hours = [h for h in window_data if
             h["cloud"] > MAX_CLOUD_PCT or
             h["precip"] > MAX_PRECIP_MM or
             h["vis"] < MIN_VISIBILITY_M]

If there are zero bad hours, the script exits with code 0 (clear). Otherwise, it exits with code 1 (not worth it).

The Output

On a clear night, the notification looks like this:

🔭 Seestar S50 — Tonight's Sky (2026-03-08)
🌑 Astronomical night: 22:34 – 03:47

✅ 22:00  ☁️8%   👁24km  🌧0.0mm  (Mainly clear)
✅ 23:00  ☁️5%   👁25km  🌧0.0mm  (Clear sky)
✅ 00:00  ☁️3%   👁25km  🌧0.0mm  (Clear sky)
✅ 01:00  ☁️10%  👁23km  🌧0.0mm  (Mainly clear)
✅ 02:00  ☁️12%  👁22km  🌧0.0mm  (Mainly clear)

🌟 CRYSTAL CLEAR — Perfect night for the Seestar! Get it set up.

On a bad night, the script runs silently — no notification, no noise.

The Cron Job

The whole thing is wired into OpenClaw as a daily cron job at 17:00 London time. The agent runs the script, checks the exit code, and routes the output to Telegram only on exit code 0:

If exit code is 0 (crystal clear tonight): send the full output to Telegram.
If exit code is 1 (not clear): stay completely silent.

Delivering alerts at 5pm gives me enough time to plan the evening — charge batteries, check the Seestar app, and get up to the roof.

What’s Next

A few things I’d like to add:

  • Seeing forecast — cloud cover isn’t everything. Atmospheric turbulence (“seeing”) affects planetary detail. Clear Outside or Meteo Blue’s seeing data would complement this.
  • Moon phase — a full moon near the target washes out faint nebulae. Worth factoring in, especially for the Orion Nebula or Andromeda.
  • Weekly outlook — instead of (or in addition to) the daily check, a Sunday evening summary showing which nights look good for the week ahead.

For now though, the 5pm notification is already doing its job. I’ve caught several clear nights I would have otherwise missed — including a particularly productive session on 11 March, where the forecast was perfect and I worked through four deep-sky targets. Here’s some of what the Seestar has pulled out of the London sky:

NGC 6995 Eastern Veil Nebula captured with Seestar S50

NGC 6995 — the Eastern Veil Nebula. Remnant of a supernova that exploded ~10,000 years ago. Seestar S50, 40 minutes integration, July 2025. The delicate shock-wave filaments are clearly resolved.

M27 Dumbbell Nebula captured with Seestar S50

M27 — the Dumbbell Nebula, a planetary nebula 1,360 light-years away. Seestar S50, 1 minute integration, July 2025. The green O-III glow and reddish H-alpha lobes visible even in a short stack.

The Seestar S50 does the hard work. This script just makes sure I don’t forget to take it outside.

M101 Pinwheel Galaxy captured with Seestar S50

M101 — the Pinwheel Galaxy, 21 million light-years away. Seestar S50, 34 minutes integration, July 2025. Spiral arms visible from a London balcony.


The full script is ~100 lines of Python. Happy to share if you want to adapt it for your location.