Skip to content

Commit 8626a27

Browse files
authored
Merge pull request #1968 from FoamyGuy/magtag_webb_telescope
magtag webb telescope status
2 parents e4a7a68 + 4be9e8c commit 8626a27

File tree

3 files changed

+10983
-0
lines changed

3 files changed

+10983
-0
lines changed

MagTag_Webb_Telescope_Status/code.py

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# SPDX-FileCopyrightText: 2022 Tim C, written for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: Unlicense
4+
"""
5+
MagTag status display for James Webb Telescope
6+
"""
7+
import time
8+
import json
9+
import ssl
10+
import board
11+
import displayio
12+
import terminalio
13+
import supervisor
14+
from adafruit_bitmap_font import bitmap_font
15+
from adafruit_display_text import bitmap_label
16+
import wifi
17+
import socketpool
18+
import alarm
19+
import adafruit_requests as requests
20+
21+
try:
22+
from secrets import secrets
23+
except ImportError:
24+
print("WiFi secrets are kept in secrets.py, please add them there!")
25+
raise
26+
27+
# Update once per hour
28+
SLEEP_TIME = 60 * 60 # seconds
29+
30+
# Update once per day
31+
# SLEEP_TIME = 60 * 60 * 24 # seconds
32+
33+
# URL to fetch the data from
34+
JSON_GET_URL = "https://api.jwst-hub.com/track"
35+
36+
# Whether to fetch live data or use cached
37+
TEST_RUN = False
38+
# Cached data, helpful when developing interface
39+
# pylint: disable=line-too-long
40+
FAKE_DATA = '{"distanceEarthKm":"1103975.4","launchElapsedTime":"15:03:47:44","distanceL2Km":342356.2,"percentageCompleted":76.3291,"speedKmS":0.3778,"deploymentImgURL":"https://webb.nasa.gov/content/webbLaunch/assets/images/deployment/1000pxWide/123Crop.png","currentDeploymentStep":"WEBB IS FULLY DEPLOYED! - The largest, most complex telescope ever launched into space is fully deployed.","tempC":{"tempWarmSide1C":55,"tempWarmSide2C":11,"tempCoolSide1C":-178,"tempCoolSide2C":-200},"timestamp":"2022-01-09T16:07:44.147Z"}'
41+
42+
# Background Color for the label texts
43+
LBL_BACKGROUND = 0x444444
44+
45+
46+
def try_refresh():
47+
"""Attempt to refresh the display. Catch 'refresh too soon' error
48+
and retry after waiting 10 seconds.
49+
"""
50+
try:
51+
board.DISPLAY.refresh()
52+
except RuntimeError as too_soon_error:
53+
# catch refresh too soon
54+
print(too_soon_error)
55+
print("waiting before retry refresh()")
56+
time.sleep(10)
57+
board.DISPLAY.refresh()
58+
59+
60+
# Get the display object
61+
display = board.DISPLAY
62+
63+
if not TEST_RUN:
64+
print("Connecting to AP...")
65+
try:
66+
# wifi connect
67+
wifi.radio.connect(secrets["ssid"], secrets["password"])
68+
69+
# Create Socket, initialize requests
70+
socket = socketpool.SocketPool(wifi.radio)
71+
requests = requests.Session(socket, ssl.create_default_context())
72+
except OSError:
73+
print("Failed to connect to AP. Rebooting in 3 seconds...")
74+
time.sleep(3)
75+
supervisor.reload()
76+
77+
78+
def make_label_text(text, anchor_point, anchored_position):
79+
"""
80+
Create label object for labeling data values.
81+
It will get a background color box and appropriate padding.
82+
83+
:param text: Text to show
84+
:param anchor_point: location anchor_point
85+
:param anchored_position: location anchored_position
86+
:return bitmap_label.Label: the Label object
87+
"""
88+
return bitmap_label.Label(
89+
font,
90+
text=text,
91+
anchor_point=anchor_point,
92+
anchored_position=anchored_position,
93+
background_color=LBL_BACKGROUND,
94+
padding_left=4,
95+
padding_right=4,
96+
padding_bottom=3,
97+
padding_top=3,
98+
)
99+
100+
101+
def make_value_text(anchor_point, anchored_position, custom_font=True):
102+
"""
103+
Create label object for showing data values.
104+
105+
:param anchor_point: location anchor_point
106+
:param anchored_position: location anchored_position
107+
:param bool custom_font: weather to use the custom font or system font
108+
:return bitmap_label.Label: the Label object
109+
"""
110+
if custom_font:
111+
_font = font
112+
else:
113+
_font = terminalio.FONT
114+
return bitmap_label.Label(
115+
_font, text="", anchor_point=anchor_point, anchored_position=anchored_position
116+
)
117+
118+
119+
# main_group to show things
120+
main_group = displayio.Group()
121+
122+
# initialize custom font
123+
font = bitmap_font.load_font("fonts/LeagueSpartan-Light.bdf")
124+
125+
# value text initialization
126+
127+
# top left
128+
elapsed_time_val = make_value_text(anchor_point=(0, 0), anchored_position=(6, 6))
129+
130+
# top right
131+
distance_from_earth_val = make_value_text(
132+
anchor_point=(1.0, 0), anchored_position=(display.width - 6, 6)
133+
)
134+
135+
# middle right
136+
distance_to_l2_val = make_value_text(
137+
anchor_point=(1.0, 0), anchored_position=(display.width - 6, 56)
138+
)
139+
140+
# bottom right
141+
percent_complete_val = make_value_text(
142+
anchor_point=(1.0, 1.0), anchored_position=(display.width - 6, display.height - 6)
143+
)
144+
145+
# middle left
146+
speed_val = make_value_text(anchor_point=(0, 0), anchored_position=(6, 56))
147+
148+
# bottom left
149+
timestamp_val = make_value_text(
150+
anchor_point=(0, 1.0), anchored_position=(6, display.height - 6), custom_font=False
151+
)
152+
153+
# center
154+
temperature_val = make_value_text(
155+
anchor_point=(0.5, 0.0), anchored_position=(display.width // 2, 6)
156+
)
157+
158+
main_group.append(elapsed_time_val)
159+
main_group.append(distance_from_earth_val)
160+
main_group.append(distance_to_l2_val)
161+
main_group.append(percent_complete_val)
162+
main_group.append(speed_val)
163+
main_group.append(timestamp_val)
164+
165+
# label text initialization
166+
167+
# top left
168+
elapsed_time_lbl = make_label_text(
169+
text="Elapsed", anchor_point=(0.0, 0), anchored_position=(6, 26)
170+
)
171+
172+
# top right
173+
distance_from_earth_lbl = make_label_text(
174+
text="From Earth", anchor_point=(1.0, 0), anchored_position=(display.width - 6, 26)
175+
)
176+
177+
# middle right
178+
distance_to_l2_lbl = make_label_text(
179+
text="To L2 Orbit", anchor_point=(1.0, 0), anchored_position=(display.width - 6, 76)
180+
)
181+
182+
# center
183+
temperature_lbl = make_label_text(
184+
text="Temp", anchor_point=(0.5, 0.0), anchored_position=(display.width // 2, 54)
185+
)
186+
187+
# middle left
188+
speed_lbl = make_label_text(
189+
text="Speed", anchor_point=(0, 0), anchored_position=(6, 76)
190+
)
191+
192+
main_group.append(elapsed_time_lbl)
193+
main_group.append(distance_from_earth_lbl)
194+
main_group.append(distance_to_l2_lbl)
195+
main_group.append(temperature_lbl)
196+
main_group.append(speed_lbl)
197+
main_group.append(temperature_val)
198+
199+
if not TEST_RUN:
200+
try:
201+
print("Fetching JSON data from %s" % JSON_GET_URL)
202+
response = requests.get(JSON_GET_URL, timeout=30)
203+
except (RuntimeError, OSError) as e:
204+
print(e)
205+
print("Failed GET request. Rebooting in 3 seconds...")
206+
time.sleep(3)
207+
supervisor.reload()
208+
209+
print("-" * 40)
210+
text_data = response.text
211+
text_data = text_data.replace('"distanceEarthKm":', '"distanceEarthKm":"').replace(
212+
',"launchElapsedTime"', '","launchElapsedTime"'
213+
)
214+
215+
json_data = json.loads(text_data)
216+
217+
print("JSON Response: ", json_data)
218+
print("-" * 40)
219+
response.close()
220+
else:
221+
json_data = json.loads(FAKE_DATA)
222+
223+
# update the labels to display values
224+
elapsed_time_val.text = json_data["launchElapsedTime"]
225+
distance_from_earth_val.text = "{}km".format(json_data["distanceEarthKm"])
226+
distance_to_l2_val.text = "{}km".format(str(json_data["distanceL2Km"]))
227+
percent_complete_val.text = "{}%".format(str(json_data["percentageCompleted"]))
228+
speed_val.text = "{}km/s".format(str(json_data["speedKmS"]))
229+
timestamp_val.text = str(json_data["timestamp"])
230+
temperature_val.text = "{}c | {}c\n{}c | {}c".format(
231+
json_data["tempC"]["tempWarmSide1C"],
232+
json_data["tempC"]["tempCoolSide1C"],
233+
json_data["tempC"]["tempWarmSide2C"],
234+
json_data["tempC"]["tempCoolSide2C"],
235+
)
236+
237+
# show the group
238+
display.show(main_group)
239+
240+
# refresh display
241+
try_refresh()
242+
243+
# Create a an alarm that will trigger to wake us up
244+
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + SLEEP_TIME)
245+
246+
# Exit the program, and then deep sleep until the alarm wakes us.
247+
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
248+
# Does not return, so we never get here.

0 commit comments

Comments
 (0)