Adafruit_Learning_System_Gu.../PyPortal_ISS_Tracker/code.py
2021-08-25 13:27:10 -04:00

131 lines
4.1 KiB
Python

import time
import math
import board
import displayio
from terminalio import FONT
from adafruit_pyportal import PyPortal
from adafruit_display_shapes.circle import Circle
from adafruit_display_text.label import Label
#--| USER CONFIG |--------------------------
MARK_SIZE = 10 # marker radius
MARK_COLOR = 0xFF3030 # marker color
MARK_THICKNESS = 5 # marker thickness
TRAIL_LENGTH = 200 # trail length
TRAIL_COLOR = 0xFFFF00 # trail color
DATE_COLOR = 0x111111 # date color
TIME_COLOR = 0x111111 # time color
LAT_MAX = 80 # latitude (deg) of map top/bottom edge
UPDATE_RATE = 10 # update rate in seconds
#-------------------------------------------
DATA_SOURCE = "http://api.open-notify.org/iss-now.json"
DATA_LOCATION = ["iss_position"]
WIDTH = board.DISPLAY.width
HEIGHT = board.DISPLAY.height
# determine the current working directory needed so we know where to find files
cwd = ("/"+__file__).rsplit('/', 1)[0]
pyportal = PyPortal(url=DATA_SOURCE,
json_path=DATA_LOCATION,
status_neopixel=board.NEOPIXEL,
text_font=None,
default_bg=cwd+"/map.bmp")
# Connect to the internet and get local time
pyportal.get_local_time()
# Date and time label
date_label = Label(FONT, text="0000-00-00", color=DATE_COLOR, x=165, y=223)
time_label = Label(FONT, text="00:00:00", color=TIME_COLOR, x=240, y=223)
pyportal.splash.append(date_label)
pyportal.splash.append(time_label)
# ISS trail
trail_bitmap = displayio.Bitmap(3, 3, 1)
trail_palette = displayio.Palette(1)
trail_palette[0] = TRAIL_COLOR
trail = displayio.Group()
pyportal.splash.append(trail)
# ISS location marker
marker = displayio.Group()
for r in range(MARK_SIZE - MARK_THICKNESS, MARK_SIZE):
marker.append(Circle(0, 0, r, outline=MARK_COLOR))
pyportal.splash.append(marker)
def get_location(width=WIDTH, height=HEIGHT):
"""Fetch current lat/lon, convert to (x, y) tuple scaled to width/height."""
# Get location
try:
location = pyportal.fetch()
except RuntimeError:
return None, None
# Compute (x, y) coordinates
lat = float(location["latitude"]) # degrees, -90 to 90
lon = float(location["longitude"]) # degrees, -180 to 180
# Scale latitude for cropped map
lat *= 90 / LAT_MAX
# Mercator projection math
# https://stackoverflow.com/a/14457180
# https://en.wikipedia.org/wiki/Mercator_projection#Alternative_expressions
x = lon + 180
x = width * x / 360
y = math.radians(lat)
y = math.tan(math.pi / 4 + y / 2)
y = math.log(y)
y = (width * y) / (2 * math.pi)
y = height / 2 - y
return int(x), int(y)
def update_display(current_time, update_iss=False):
"""Update the display with current info."""
# ISS location
if update_iss:
x, y = get_location()
if x and y:
marker.x = x
marker.y = y
if len(trail) >= TRAIL_LENGTH:
trail.pop(0)
trail.append(displayio.TileGrid(trail_bitmap,
pixel_shader=trail_palette,
x = x - 1,
y = y - 1) )
# Date and time
date_label.text = "{:04}-{:02}-{:02}".format(current_time.tm_year,
current_time.tm_mon,
current_time.tm_mday)
time_label.text = "{:02}:{:02}:{:02}".format(current_time.tm_hour,
current_time.tm_min,
current_time.tm_sec)
try:
board.DISPLAY.refresh(target_frames_per_second=60)
except AttributeError:
board.DISPLAY.refresh_soon()
# Initial refresh
update_display(time.localtime(), True)
last_update = time.monotonic()
# Run forever
while True:
now = time.monotonic()
new_position = False
if now - last_update > UPDATE_RATE:
new_position = True
last_update = now
update_display(time.localtime(), new_position)
time.sleep(0.5)