Skip to content

Commit

Permalink
Merge pull request #1 from TristanAmond/weather-data
Browse files Browse the repository at this point in the history
Weather Display Support
  • Loading branch information
TristanAmond authored Mar 23, 2023
2 parents e9f5113 + e17b69c commit e432a7b
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 11 deletions.
54 changes: 54 additions & 0 deletions bdf/trend_icons.bdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
STARTFONT 2.1
FONT -Trend Icon Set
SIZE 20 75 75
FONTBOUNDINGBOX 39 31 -11 -6
STARTPROPERTIES 40
FONT_ASCENT 17
FONT_DESCENT 4
UNDERLINE_POSITION -1
UNDERLINE_THICKNESS 2
X_HEIGHT 10
CAP_HEIGHT 14
DEFAULT_CHAR 1
RAW_ASCENT 800
RAW_DESCENT 200
NORM_SPACE 6
RELATIVE_WEIGHT 70
RELATIVE_SETWIDTH 50
SUPERSCRIPT_X 0
SUPERSCRIPT_Y 7
SUPERSCRIPT_SIZE 12
SUBSCRIPT_X 0
SUBSCRIPT_Y 1
SUBSCRIPT_SIZE 12
AVG_LOWERCASE_WIDTH 109
AVG_UPPERCASE_WIDTH 142
ENDPROPERTIES
CHARS 1300
STARTCHAR NULL
ENCODING 0
SWIDTH 0 0
DWIDTH 0 0
BBX 1 1 0 0
BITMAP
00
ENDCHAR
STARTCHAR comma
ENCODING 44
SWIDTH 333 0
DWIDTH 5 0
BBX 3 4 1 -2
BITMAP
40
A0
ENDCHAR
STARTCHAR period
ENCODING 46
SWIDTH 333 0
DWIDTH 5 0
BBX 3 4 1 -2
BITMAP
A0
40
ENDCHAR
ENDFONT
Binary file added bmp/weather-icons.bmp
Binary file not shown.
121 changes: 121 additions & 0 deletions code.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
import busio
from digitalio import DigitalInOut, Pull
import neopixel

from adafruit_matrixportal.matrix import Matrix
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager

import json
import display_manager

print("All imports loaded | Available memory: {} bytes".format(gc.mem_free()))

# --- CONSTANTS SETUP ---

try:
Expand All @@ -22,6 +26,17 @@
station_code = secrets["station_code"]
historical_trains = [None, None]

# weather data dict
weather_data = {}
# daily highest temperature
# max_temp, day of the year
highest_temp = [None,None]
# daily lowest temperature
# min_temp, day of the year
lowest_temp = [None, None]
# current temp (for historical)
current_temp = []

# --- DISPLAY SETUP ---

# MATRIX DISPLAY MANAGER
Expand Down Expand Up @@ -110,11 +125,117 @@ def get_trains(StationCode, historical_trains):
pass
return trains

# queries Openweather API to return a dict with current and 3 hr forecast weather data
# input is latitude and longitude coordinates for weather location
def get_weather(weather_data):
try:
# query Openweather for weather at location defined by input lat, long
base_URL = 'https://api.openweathermap.org/data/3.0/onecall?'
latitude = secrets['dc coords x']
longitude = secrets['dc coords y']
units = 'imperial'
api_key = secrets['openweather api key']
exclude = 'minutely,alerts'
response = wifi.get(base_URL
+'lat='+latitude
+'&lon='+longitude
+'&exclude='+exclude
+'&units='+units
+'&appid='+api_key
)
weather_json = response.json()
del response

# insert icon and current weather data into dict
weather_data["icon"] = weather_json["current"]["weather"][0]["icon"]
weather_data["current_temp"] = weather_json["current"]["temp"]
weather_data["current_feels_like"] = weather_json["current"]["feels_like"]
# insert daily forecast min and max temperature into dict
weather_data["daily_temp_min"] = weather_json["daily"][0]["temp"]["min"]
weather_data["daily_temp_max"] = weather_json["daily"][0]["temp"]["max"]
# insert next hour + 1 forecast temperature and feels like into dict
weather_data["hourly_next_temp"] = weather_json["hourly"][2]["temp"]
weather_data["hourly_feels_like"] = weather_json["hourly"][2]["feels_like"]

# set daily highest temperature
global highest_temp
global current_time
# if daily highest temperature hasn't been set or is from a previous day
if highest_temp[0] is None or highest_temp[1] != current_time.tm_wday:
highest_temp[0] = weather_data["daily_temp_max"]
highest_temp[1] = current_time.tm_wday
print("Daily highest temp set to {}".format(highest_temp[0]))
# if stored highest temp is less than new highest temp
elif highest_temp[0] < weather_data["daily_temp_max"]:
highest_temp[0] = weather_data["daily_temp_max"]
print("Daily highest temp set to {}".format(highest_temp[0]))
# if stored highest temp is greater than new highest temp
elif highest_temp[0] > weather_data["daily_temp_max"]:
weather_data["daily_temp_max"] = highest_temp[0]
print("Daily highest temp pulled from historical data")

# set daily lowest temperature
global lowest_temp
# if daily lowest temperature hasn't been set or is from a previous day
if lowest_temp[0] is None or lowest_temp[1] != current_time.tm_wday:
lowest_temp[0] = weather_data["daily_temp_min"]
lowest_temp[1] = current_time.tm_wday
print("Daily lowest temp set to {}".format(lowest_temp[0]))
# if daily lowest temp is greater than new lowest temp
elif lowest_temp[0] > weather_data["daily_temp_min"]:
lowest_temp[0] = weather_data["daily_temp_min"]
print("Daily lowest temp set to {}".format(lowest_temp[0]))
# if daily lowest temp is less than new lowest temp
elif lowest_temp[0] < weather_data["daily_temp_min"]:
weather_data["daily_temp_min"] = lowest_temp[0]
print("Daily lowest temp pulled from historical data")

# add current temp to historical array
global current_temp
current_temp.append(weather_data["current_temp"])
# clean up response
del weather_json

# return dict with relevant data
return True

except Exception as e:
print("Failed to get data, retrying\n", e)
wifi.reset()

# --- TIME MGMT FUNCTIONS ---

def check_time():
base_url = "http://io.adafruit.com/api/v2/time/seconds"
try:
response = wifi.get(base_url)
epoch_time = int(response.text)
del response

global current_time
current_time = time.localtime(epoch_time)
except Exception as e:
print(e)
wifi.reset()

# --- OPERATING LOOP ------------------------------------------
loop_counter=1
last_weather_check=None
last_train_check=None

while True:
check_time()

# fetch weather data on start and recurring (default: 10 minutes)
if last_weather_check is None or time.monotonic() > last_weather_check + 60 * 10:
weather = get_weather(weather_data)
if weather:
last_weather_check = time.monotonic()
print("weather updated")
# update weather display component
display_manager.update_weather(weather_data)
else:pass

# update train data (default: 15 seconds)
if last_train_check is None or time.monotonic() > last_train_check + 15:
trains = get_trains(station_code, historical_trains)
Expand Down
Loading

0 comments on commit e432a7b

Please sign in to comment.