while running the project i realized i had forgotten the text update line after adding in the functions
187 lines
5.3 KiB
Python
187 lines
5.3 KiB
Python
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import os
|
|
import ssl
|
|
import time
|
|
import board
|
|
import wifi
|
|
import socketpool
|
|
import fontio
|
|
import neopixel
|
|
import simpleio
|
|
from adafruit_display_text.bitmap_label import Label
|
|
from adafruit_bitmap_font import bitmap_font
|
|
from displayio import Bitmap
|
|
from rainbowio import colorwheel
|
|
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
|
|
import adafruit_requests
|
|
from weather_codes import weather_codes
|
|
|
|
# minimum expected temperature
|
|
min_temp = 0
|
|
# maximum expected temperature
|
|
max_temp = 100
|
|
# first daylight hour
|
|
daytime_min = 7
|
|
# last daylight hour
|
|
daytime_max = 17
|
|
# latitude
|
|
lat = 42.36
|
|
# longitude
|
|
long = -71.06
|
|
# temp unit for API request
|
|
temperature_unit = "fahrenheit"
|
|
# temp unit for display
|
|
temp_unit = "F"
|
|
|
|
# API request to open-meteo
|
|
weather_url = "https://api.open-meteo.com/v1/forecast?"
|
|
# pass latitude and longitude
|
|
weather_url += "latitude=%d&longitude=%d&timezone=auto" % (lat, long)
|
|
# pass temperature_unit
|
|
weather_url += "¤t_weather=true&temperature_unit=%s&windspeed_unit=mph" % temperature_unit
|
|
|
|
# connect to SSID
|
|
wifi.radio.connect(os.getenv('WIFI_SSID'), os.getenv('WIFI_PASSWORD'))
|
|
|
|
pool = socketpool.SocketPool(wifi.radio)
|
|
requests = adafruit_requests.Session(pool, ssl.create_default_context())
|
|
|
|
def get_the_weather():
|
|
# make the API request
|
|
response = requests.get(weather_url)
|
|
# packs the response into a JSON
|
|
response_as_json = response.json()
|
|
print()
|
|
# prints the entire JSON
|
|
print(response_as_json)
|
|
print()
|
|
# gets current weather code
|
|
w = int(response_as_json['current_weather']['weathercode'])
|
|
# gets temperature
|
|
t = response_as_json['current_weather']['temperature']
|
|
temp_int = int(t)
|
|
t_c = simpleio.map_range(temp_int, min_temp, max_temp, 255, 0)
|
|
# gets time
|
|
json_time = response_as_json['current_weather']['time']
|
|
n_t = json_time.rsplit("T", 1)[-1]
|
|
n_t = int(n_t[:2])
|
|
return w, t, t_c, n_t
|
|
|
|
# initial API call
|
|
weather, temp, temp_color, new_time = get_the_weather()
|
|
|
|
# font edit code by Jeff Epler
|
|
tom_thumb = bitmap_font.load_font("tom-thumb.pcf", Bitmap)
|
|
|
|
_glyph_keys = ['bitmap', 'tile_index', 'width', 'height', 'dx', 'dy', 'shift_x', 'shift_y']
|
|
def patch_glyph(base, **kw):
|
|
d = {}
|
|
for k in _glyph_keys:
|
|
d[k] = kw.get(k, getattr(base, k))
|
|
return fontio.Glyph(**d)
|
|
|
|
class PatchedFont:
|
|
def __init__(self, base_font, patches):
|
|
self.base_font = base_font
|
|
self.patches = patches
|
|
|
|
def get_glyph(self, glyph):
|
|
g = self.base_font.get_glyph(glyph)
|
|
patch = self.patches.get(glyph)
|
|
if patch is not None:
|
|
#print("patching", repr(chr(glyph)), g)
|
|
g = patch_glyph(g, **patch)
|
|
#print("patched", g)
|
|
return g
|
|
|
|
def get_bounding_box(self):
|
|
return self.base_font.get_bounding_box()
|
|
|
|
font = PatchedFont(tom_thumb,
|
|
{
|
|
32: {'shift_x': 1, 'dx': 0},
|
|
105: {'dx': 0, 'shift_x': 2},
|
|
33: {'dx': 0, 'shift_x': 2},
|
|
})
|
|
# thank you Jeff for this PatchedFont() function!
|
|
|
|
# temperature for scrolling text
|
|
label = Label(text=" %s°%s " % (temp, temp_unit), font=font)
|
|
text = label.bitmap
|
|
|
|
# create 5x5 neopixels
|
|
pixels = neopixel.NeoPixel(board.A3, 5*5, brightness=.08, auto_write=False)
|
|
# count for pixels when drawing bitmaps
|
|
count = 0
|
|
# arrays to pack assets from weather_codes helper
|
|
# weather condition code
|
|
codes = []
|
|
# bitmaps for daytime
|
|
day_images = []
|
|
# bitmaps for nighttime
|
|
night_images = []
|
|
|
|
for i in weather_codes:
|
|
codes.append(i['code'])
|
|
day_images.append(i['day_img'])
|
|
night_images.append(i['night_img'])
|
|
|
|
# checks if it's day or night based on hour
|
|
def day_or_night(t):
|
|
if t in range(daytime_min, daytime_max):
|
|
z = day_images[weather]
|
|
else:
|
|
z = night_images[weather]
|
|
return z
|
|
|
|
# initial sprite selection
|
|
img = day_or_night(new_time)
|
|
|
|
# draw bitmap sprite
|
|
def draw_sprite(c):
|
|
for pixel in img:
|
|
pixels[c] = pixel
|
|
pixels.show()
|
|
c += 1
|
|
time.sleep(0.001)
|
|
c = 0
|
|
|
|
# ticks time tracker
|
|
clock = ticks_ms()
|
|
|
|
# 15 minutes in milliseconds
|
|
weather_check = 900000
|
|
|
|
# display current weather sprite & scroll temperature
|
|
while True:
|
|
# checks the time
|
|
if ticks_diff(ticks_ms(), clock) > weather_check:
|
|
print("pinging Open-Meteo")
|
|
# make the API request with function
|
|
# return weather ID, temp, temp color & hour
|
|
weather, temp, temp_color, new_time = get_the_weather()
|
|
# checks if it's day or night based on hour
|
|
# & returns day or night version of sprite
|
|
img = day_or_night(new_time)
|
|
label.text = " %s°%s " % (temp, temp_unit)
|
|
# reset clock
|
|
clock = ticks_add(clock, weather_check)
|
|
# draw bitmap sprite
|
|
draw_sprite(count)
|
|
# blocking delay to hold the sprite on the display
|
|
time.sleep(5)
|
|
# draw scrolling text
|
|
for v in range(2):
|
|
for i in range(text.width):
|
|
# Scoot the old text left by 1 pixel
|
|
pixels[:20] = pixels[5:]
|
|
# adjust color based on temperature
|
|
color = colorwheel(temp_color)
|
|
# Draw in the next line of text
|
|
for y in range(5):
|
|
# Select black or color depending on the bitmap pixel
|
|
pixels[20+y] = color * text[i,y]
|
|
pixels.show()
|
|
time.sleep(.1)
|