-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdaylight_print.py
More file actions
104 lines (86 loc) · 4.26 KB
/
Copy pathdaylight_print.py
File metadata and controls
104 lines (86 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env python3
"""Print today's daylight (sunrise/sunset) on the S01 thermal printer.
Pulls sun times for a location from sunrise-sunset.org, draws the sun's arc
across the sky with the current position marked, and lists first light, sunrise,
solar noon, sunset, last light, and day length. Times are shown in your local
timezone.
Examples:
python daylight_print.py # default location
python daylight_print.py --lat 40.71 --lng -74.0 --place "New York"
python daylight_print.py --no-print
"""
from __future__ import annotations
import argparse
from datetime import datetime, timezone
from math import cos, pi, radians, sin
from pathlib import Path
from PIL import Image, ImageDraw
from print_common import ROOT, Card, font, get_json
API = "https://api.sunrise-sunset.org/json?lat={lat}&lng={lng}&formatted=0"
def local(iso: str) -> datetime:
return datetime.fromisoformat(iso).astimezone()
def draw_arc(sunrise: datetime, sunset: datetime, now: datetime, w: int, h: int = 150) -> Image.Image:
img = Image.new("L", (w, h), 255)
d = ImageDraw.Draw(img)
margin = 30
horizon = h - 22
arc_h = horizon - 14
steps = 120
pts = [(margin + t / steps * (w - 2 * margin), horizon - sin(pi * t / steps) * arc_h)
for t in range(steps + 1)]
d.line(pts, fill=0, width=2)
d.line((0, horizon, w, horizon), fill=0, width=1)
# endpoint ticks + labels
tiny = font(False, 11)
d.line((margin, horizon - 5, margin, horizon + 5), fill=0, width=2)
d.line((w - margin, horizon - 5, w - margin, horizon + 5), fill=0, width=2)
d.text((margin, horizon + 6), "rise", fill=0, font=tiny, anchor="ma")
d.text((w - margin, horizon + 6), "set", fill=0, font=tiny, anchor="ma")
# current sun position along the arc
span = (sunset - sunrise).total_seconds()
f = (now - sunrise).total_seconds() / span if span else 0
night = f < 0 or f > 1
f = min(1.0, max(0.0, f))
sx = margin + f * (w - 2 * margin)
sy = horizon - sin(pi * f) * arc_h
r = 7
if night:
d.ellipse((sx - r, sy - r, sx + r, sy + r), outline=0, width=2) # hollow = below horizon
else:
d.ellipse((sx - r, sy - r, sx + r, sy + r), fill=0)
for ang in range(0, 360, 45):
dx, dy = cos(radians(ang)), sin(radians(ang))
d.line((sx + dx * (r + 2), sy + dy * (r + 2), sx + dx * (r + 6), sy + dy * (r + 6)), fill=0, width=1)
return img
def main() -> int:
parser = argparse.ArgumentParser(description="Print today's daylight on the S01 thermal printer.")
parser.add_argument("--lat", type=float, default=40.7128, help="Latitude (default: New York).")
parser.add_argument("--lng", type=float, default=-74.0060, help="Longitude (default: New York).")
parser.add_argument("--place", default="New York", help="Place label for the header.")
parser.add_argument("--out", type=Path, default=ROOT / "daylight.png")
parser.add_argument("--darkness", type=int, choices=range(1, 6), default=3)
parser.add_argument("--bottom-feed", type=int, default=24)
parser.add_argument("--no-print", action="store_true")
args = parser.parse_args()
print(f"Fetching sun times for {args.place} ...")
res = get_json(API.format(lat=args.lat, lng=args.lng))["results"]
sunrise, sunset = local(res["sunrise"]), local(res["sunset"])
secs = int(res["day_length"])
day_len = f"{secs // 3600}h {secs % 3600 // 60}m"
now = datetime.now(timezone.utc).astimezone()
print(f" sunrise {sunrise:%H:%M} sunset {sunset:%H:%M} ({day_len})")
card = Card()
card.title("DAYLIGHT")
card.heading(f"{args.place} - {sunrise:%b %d}", size=15)
card.gap(4).image(draw_arc(sunrise, sunset, now, card.inner_w), border=True)
card.gap(2).divider()
card.kv("First light", f"{local(res['civil_twilight_begin']):%H:%M}")
card.kv("Sunrise", f"{sunrise:%H:%M}")
card.kv("Solar noon", f"{local(res['solar_noon']):%H:%M}")
card.kv("Sunset", f"{sunset:%H:%M}")
card.kv("Last light", f"{local(res['civil_twilight_end']):%H:%M}")
card.kv("Day length", day_len)
card.footer("sunrise-sunset.org", now.strftime("%Y-%m-%d %H:%M"))
return card.finish(args.out, args.bottom_feed, args.darkness, do_print=not args.no_print)
if __name__ == "__main__":
raise SystemExit(main())