The suntime library uses a simplified approximation that degrades at high
latitudes as sunrise approaches very early hours near the summer solstice.
The computed sunrise drifted progressively earlier than the actual event,
shrinking the capture window until today it ended before the sun rose.
Switch to skyfield's sunrise_sunset almanac (DE421 ephemeris), which is
accurate to within a second at any latitude — the same library already
used by moon_phase.py for sun events. The search window is anchored to
local midnight→midnight UTC so the correct calendar-day sunrise is
always returned regardless of timezone offset.
Also promote skyfield to the core pip install in bootstrap.sh (dropping
suntime, which is no longer needed) and tidy the stale "suntime" hints
in 4-seasons.sh and montage-mvt.sh error messages.
https://claude.ai/code/session_01S4oUbU9xNj91cbV5bj5NRn
Two new jobs operate on the SUNRISE_CAM, sharing three Python helpers
(moon_phase, moon_detect, moon_composite) and one cached lunar texture:
- moon-track.sh: nightly batch detects the moon in each east frame,
crops a 480x480 box around it, stitches into an mp4 that holds the
moon roughly centred while clouds and stars drift past.
- moon-phase-monthly.sh: daily check that runs whichever phase composite
is due that day. Handles full moon (posts D+3), first quarter (D+2,
best-effort due to daytime-only geometry from east), and third quarter
(D+2). Picks the frame closest in time to the exact phase moment that
meets quality / altitude / illumination thresholds, then composites
the cached lunar texture into it -- sky/halo/parallactic-angle/timing
real from east, surface detail borrowed from the reference image.
Honest-by-design: a 38-px white blob from a wide-field IP camera cannot
be enhanced into crater detail by software. The composite makes the
borrowing explicit and constrains everything else (when, where, sky,
orientation) to match what east actually saw.
install.sh now downloads the skyfield ephemeris (de421.bsp) and the
default lunar reference (Wikipedia CC BY-SA full-moon photo) on first
run. Both can be overridden via .env.
https://claude.ai/code/session_015PBVDESC3KLMbq1LpA6qLn
Cameras are now named by direction (east, north, south, west) throughout
config defaults, examples, and documentation. The config key SUNRISE_CAM
is unchanged — it still means 'which camera faces east and gets the sunrise
job'. Only the camera instance name value changes from 'sunrise' to 'east'.
sky-cam.conf: CAMERAS=(east), SUNRISE_CAM=east, SCHEDULE_*_east,
example comments updated to show all four compass points.
README.md: all command examples updated (4-seasons.sh east, journalctl
sky-cam-capture-east, etc.) — phenomenon references ('sunrise window',
'sunrise time') left unchanged.
bootstrap.sh: example updated to show compass directions.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
daily_sunrise_video.sh: use \$MOVIES_DIR instead of \$BASE_DIR/movies so the
override in sky-cam.conf is respected when videos live on a separate drive.
capture.sh: default camera name falls back to \$SUNRISE_CAM (not the
undefined \$CAM_NAME) when no argument is passed.
sunrise2mm.py: also loads .env after sky-cam.conf so Mattermost credentials
moved to .env are actually visible to the upload script.
sunrise.py: raise a clear error message when LATITUDE/LONGITUDE/TIMEZONE
are missing from sky-cam.conf instead of an opaque KeyError.
4-seasons.sh, montage-mvt.sh: capture season_info.py output before eval so
a Python failure exits cleanly with a diagnostic message rather than
silently continuing with undefined variables.
bootstrap.sh: add system package install step (ffmpeg bc fonts-dejavu) and
show the .env setup step after install.sh generates .env.example.
README.md: correct Python package names and add fonts-dejavu dependency.
https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ