Skip to content

Commit 41cf9c4

Browse files
authored
Merge pull request #704 from caternuson/pp_iss_tracker
Add PyPortal ISS Tracker code
2 parents 79c2d5e + 53797f9 commit 41cf9c4

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

PyPortal_ISS_Tracker/map.bmp

76.1 KB
Binary file not shown.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import time
2+
import math
3+
import board
4+
import displayio
5+
from terminalio import FONT
6+
from adafruit_pyportal import PyPortal
7+
from adafruit_display_shapes.circle import Circle
8+
from adafruit_display_text.label import Label
9+
10+
#--| USER CONFIG |--------------------------
11+
MARK_SIZE = 10 # marker radius
12+
MARK_COLOR = 0xFF3030 # marker color
13+
MARK_THICKNESS = 5 # marker thickness
14+
TRAIL_LENGTH = 200 # trail length
15+
TRAIL_COLOR = 0xFFFF00 # trail color
16+
DATE_COLOR = 0x111111 # date color
17+
TIME_COLOR = 0x111111 # time color
18+
LAT_MAX = 80 # latitude (deg) of map top/bottom edge
19+
UPDATE_RATE = 10 # update rate in seconds
20+
#-------------------------------------------
21+
22+
DATA_SOURCE = "http://api.open-notify.org/iss-now.json"
23+
DATA_LOCATION = ["iss_position"]
24+
25+
WIDTH = board.DISPLAY.width
26+
HEIGHT = board.DISPLAY.height
27+
28+
# determine the current working directory needed so we know where to find files
29+
cwd = ("/"+__file__).rsplit('/', 1)[0]
30+
pyportal = PyPortal(url=DATA_SOURCE,
31+
json_path=DATA_LOCATION,
32+
status_neopixel=board.NEOPIXEL,
33+
default_bg=cwd+"/map.bmp")
34+
35+
# Connect to the internet and get local time
36+
pyportal.get_local_time()
37+
38+
# Date and time label
39+
date_label = Label(FONT, text="0000-00-00", color=DATE_COLOR, x=165, y=223)
40+
time_label = Label(FONT, text="00:00:00", color=TIME_COLOR, x=240, y=223)
41+
pyportal.splash.append(date_label)
42+
pyportal.splash.append(time_label)
43+
44+
# ISS trail
45+
trail_bitmap = displayio.Bitmap(3, 3, 1)
46+
trail_palette = displayio.Palette(1)
47+
trail_palette[0] = TRAIL_COLOR
48+
trail = displayio.Group(max_size=TRAIL_LENGTH)
49+
pyportal.splash.append(trail)
50+
51+
# ISS location marker
52+
marker = displayio.Group(max_size=MARK_THICKNESS)
53+
for r in range(MARK_SIZE - MARK_THICKNESS, MARK_SIZE):
54+
marker.append(Circle(0, 0, r, outline=MARK_COLOR))
55+
pyportal.splash.append(marker)
56+
57+
def get_location(width=WIDTH, height=HEIGHT):
58+
"""Fetch current lat/lon, convert to (x, y) tuple scaled to width/height."""
59+
60+
# Get location
61+
try:
62+
location = pyportal.fetch()
63+
except RuntimeError:
64+
return None, None
65+
66+
# Compute (x, y) coordinates
67+
lat = float(location["latitude"]) # degrees, -90 to 90
68+
lon = float(location["longitude"]) # degrees, -180 to 180
69+
70+
# Scale latitude for cropped map
71+
lat *= 90 / LAT_MAX
72+
73+
# Mercator projection math
74+
# https://stackoverflow.com/a/14457180
75+
# https://en.wikipedia.org/wiki/Mercator_projection#Alternative_expressions
76+
x = lon + 180
77+
x = width * x / 360
78+
79+
y = math.radians(lat)
80+
y = math.tan(math.pi / 4 + y / 2)
81+
y = math.log(y)
82+
y = (width * y) / (2 * math.pi)
83+
y = height / 2 - y
84+
85+
return int(x), int(y)
86+
87+
def update_display(current_time, update_iss=False):
88+
"""Update the display with current info."""
89+
90+
# ISS location
91+
if update_iss:
92+
x, y = get_location()
93+
if x and y:
94+
marker.x = x
95+
marker.y = y
96+
if len(trail) >= TRAIL_LENGTH:
97+
trail.pop(0)
98+
trail.append(displayio.TileGrid(trail_bitmap,
99+
pixel_shader=trail_palette,
100+
x = x - 1,
101+
y = y - 1) )
102+
103+
104+
# Date and time
105+
date_label.text = "{:04}-{:02}-{:02}".format(current_time.tm_year,
106+
current_time.tm_mon,
107+
current_time.tm_mday)
108+
time_label.text = "{:02}:{:02}:{:02}".format(current_time.tm_hour,
109+
current_time.tm_min,
110+
current_time.tm_sec)
111+
112+
board.DISPLAY.refresh_soon()
113+
114+
# Initial refresh
115+
update_display(time.localtime(), True)
116+
last_update = time.monotonic()
117+
118+
# Run forever
119+
while True:
120+
now = time.monotonic()
121+
new_position = False
122+
if now - last_update > UPDATE_RATE:
123+
new_position = True
124+
last_update = now
125+
update_display(time.localtime(), new_position)
126+
time.sleep(0.5)

0 commit comments

Comments
 (0)