Skip to content

Commit fd82450

Browse files
authored
Merge branch 'master' into sharpdisplay-example
2 parents 0fb5c98 + b33ad19 commit fd82450

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

Daily_Cheer_Automaton/autocheer/autocheer.ino

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ DST_RTC dst_rtc; // DST object
111111
// you'll need to modify the code in the DST_RTC library to make this work properly.
112112
#define OBSERVE_DST 1
113113

114+
// Define US or EU rules for DST comment out as required. More countries could be added with different rules in DST_RTC.cpp
115+
const char rulesDST[] = "US"; // US DST rules
116+
// const char rulesDST[] = "EU"; // EU DST rules
117+
114118
// the hour and minute you'd like MP3 to start playing
115119
const int PLAYHOUR = 19; // 24 hour time
116120
const int PLAYMIN = 0;
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import time
2+
import math
3+
import board
4+
import displayio
5+
import terminalio
6+
from simpleio import map_range
7+
import adafruit_imageload
8+
from adafruit_pyportal import PyPortal
9+
from adafruit_display_text.label import Label
10+
from adafruit_display_shapes.line import Line
11+
12+
# --| User Config |---------------------------------------------------
13+
UPDATE_RATE = 60 # minutes
14+
MAX_STORMS = 3 # limit storms
15+
NAME_COLOR = 0xFFFFFF # label text color
16+
NAME_BG_COLOR = 0x000000 # label background color
17+
ARROW_COLOR = 0x0000FF # movement direction arrow color
18+
ARROW_LENGTH = 15 # movement direction arrow length
19+
LAT_RANGE = (45, 5) # set to match map
20+
LON_RANGE = (-100, -40) # set to match map
21+
# --------------------------------------------------------------------
22+
23+
# setup pyportal
24+
pyportal = PyPortal(
25+
url="https://www.nhc.noaa.gov/CurrentStorms.json",
26+
json_path=["activeStorms"],
27+
status_neopixel=board.NEOPIXEL,
28+
default_bg="/map.bmp",
29+
)
30+
31+
# setup display group for storms
32+
icons_bmp, icons_pal = adafruit_imageload.load(
33+
"/storm_icons.bmp", bitmap=displayio.Bitmap, palette=displayio.Palette
34+
)
35+
for i, c in enumerate(icons_pal):
36+
if c == 0xFFFF00:
37+
icons_pal.make_transparent(i)
38+
storm_icons = displayio.Group(max_size=MAX_STORMS)
39+
pyportal.splash.append(storm_icons)
40+
STORM_CLASS = ("TD", "TS", "HU")
41+
42+
# setup info label
43+
info_update = Label(
44+
terminalio.FONT,
45+
text="1984-01-01T00:00:00.000Z",
46+
color=NAME_COLOR,
47+
background_color=NAME_BG_COLOR,
48+
)
49+
info_update.anchor_point = (0.0, 1.0)
50+
info_update.anchored_position = (10, board.DISPLAY.height - 10)
51+
pyportal.splash.append(info_update)
52+
53+
# these are need for lat/lon to screen x/y mapping
54+
VIRTUAL_WIDTH = board.DISPLAY.width * 360 / (LON_RANGE[1] - LON_RANGE[0])
55+
VIRTUAL_HEIGHT = board.DISPLAY.height * 360 / (LAT_RANGE[0] - LAT_RANGE[1])
56+
Y_OFFSET = math.radians(LAT_RANGE[0])
57+
Y_OFFSET = math.tan(math.pi / 4 + Y_OFFSET / 2)
58+
Y_OFFSET = math.log(Y_OFFSET)
59+
Y_OFFSET = (VIRTUAL_WIDTH * Y_OFFSET) / (2 * math.pi)
60+
Y_OFFSET = VIRTUAL_HEIGHT / 2 - Y_OFFSET
61+
62+
63+
def update_display():
64+
# clear out existing icons
65+
while len(storm_icons):
66+
_ = storm_icons.pop()
67+
68+
# get latest storm data
69+
try:
70+
storm_data = pyportal.fetch()
71+
except RuntimeError:
72+
return
73+
print("Number of storms:", len(storm_data))
74+
75+
# parse the storm data
76+
for storm in storm_data:
77+
# don't exceed max
78+
if len(storm_icons) >= MAX_STORMS:
79+
continue
80+
# get lat/lon
81+
lat = storm["latitudeNumeric"]
82+
lon = storm["longitudeNumeric"]
83+
# check if on map
84+
if (
85+
not LAT_RANGE[0] >= lat >= LAT_RANGE[1]
86+
or not LON_RANGE[0] <= lon <= LON_RANGE[1]
87+
):
88+
continue
89+
# OK, let's make a group for all the graphics
90+
storm_gfx = displayio.Group(max_size=3) # icon + label + arrow
91+
# convert to sreen coords
92+
x = int(map_range(lon, LON_RANGE[0], LON_RANGE[1], 0, board.DISPLAY.width - 1))
93+
y = math.radians(lat)
94+
y = math.tan(math.pi / 4 + y / 2)
95+
y = math.log(y)
96+
y = (VIRTUAL_WIDTH * y) / (2 * math.pi)
97+
y = VIRTUAL_HEIGHT / 2 - y
98+
y = int(y - Y_OFFSET)
99+
# icon type
100+
if storm["classification"] in STORM_CLASS:
101+
storm_type = STORM_CLASS.index(storm["classification"])
102+
else:
103+
storm_type = 0
104+
# create storm icon
105+
icon = displayio.TileGrid(
106+
icons_bmp,
107+
pixel_shader=icons_pal,
108+
width=1,
109+
height=1,
110+
tile_width=16,
111+
tile_height=16,
112+
default_tile=storm_type,
113+
x=x - 8,
114+
y=y - 8,
115+
)
116+
# add storm icon
117+
storm_gfx.append(icon)
118+
# add a label
119+
name = Label(
120+
terminalio.FONT,
121+
text=storm["name"],
122+
color=NAME_COLOR,
123+
background_color=NAME_BG_COLOR,
124+
)
125+
name.anchor_point = (0.0, 1.0)
126+
name.anchored_position = (x + 8, y - 8)
127+
storm_gfx.append(name)
128+
# add direction arrow
129+
angle = math.radians(storm["movementDir"])
130+
xd = x + int(ARROW_LENGTH * math.sin(angle))
131+
yd = y - int(ARROW_LENGTH * math.cos(angle))
132+
arrow = Line(x, y, xd, yd, color=ARROW_COLOR)
133+
storm_gfx.append(arrow)
134+
# add the storm graphics
135+
storm_icons.append(storm_gfx)
136+
# update time
137+
info_update.text = storm["lastUpdate"]
138+
# debug
139+
print(
140+
"{} @ {},{}".format(
141+
storm["name"], storm["latitudeNumeric"], storm["longitudeNumeric"]
142+
)
143+
)
144+
145+
# no storms? at least say something
146+
if not len(storm_icons):
147+
print("No storms in map area.")
148+
storm_icons.append(
149+
Label(
150+
terminalio.FONT,
151+
scale=4,
152+
x=50,
153+
y=110,
154+
text="NO STORMS\n IN AREA",
155+
color=NAME_COLOR,
156+
background_color=NAME_BG_COLOR,
157+
)
158+
)
159+
160+
161+
# --------------------------------------------------------------------
162+
# M A I N
163+
# --------------------------------------------------------------------
164+
update_display()
165+
last_update = time.monotonic()
166+
while True:
167+
now = time.monotonic()
168+
if now - last_update > UPDATE_RATE * 60:
169+
print("Updating...")
170+
update_display()
171+
last_update = now

PyPortal_Hurricane_Tracker/map.bmp

37.7 KB
Binary file not shown.
534 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)