Merge pull request #2355 from adafruit/weather_sprites
Adding code for qt py neopixel weather display
This commit is contained in:
commit
bf15ca13aa
2 changed files with 374 additions and 0 deletions
183
NeoPixel_Sprite_Weather_Display/code.py
Normal file
183
NeoPixel_Sprite_Weather_Display/code.py
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# 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
|
||||
|
||||
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())
|
||||
|
||||
# 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
|
||||
weather = int(response_as_json['current_weather']['weathercode'])
|
||||
print(weather)
|
||||
# gets temperature
|
||||
temp = response_as_json['current_weather']['temperature']
|
||||
temp_int = int(temp)
|
||||
print("%s°%s" % (temp, temp_unit))
|
||||
# gets time
|
||||
json_time = response_as_json['current_weather']['time']
|
||||
new_time = json_time.rsplit("T", 1)[-1]
|
||||
new_time = int(new_time[:2])
|
||||
print(new_time)
|
||||
|
||||
# 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},
|
||||
})
|
||||
|
||||
# temperature for scrolling text
|
||||
label = Label(text=" %s°%s " % (temp, temp_unit), font=font)
|
||||
bitmap = 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 = []
|
||||
# bitmap for daytime
|
||||
day_images = []
|
||||
# bitmap 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'])
|
||||
|
||||
clock = time.monotonic()
|
||||
|
||||
# display current weather sprite & scroll temperature
|
||||
while True:
|
||||
# check every hour
|
||||
if (time.monotonic() - clock) > 3600:
|
||||
# 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()
|
||||
# current weather code
|
||||
weather = int(response_as_json['current_weather']['weathercode'])
|
||||
print(weather)
|
||||
# temperature
|
||||
temp = response_as_json['current_weather']['temperature']
|
||||
temp_int = int(temp)
|
||||
print("%s°%s" % (temp, temp_unit))
|
||||
# update scrolling text
|
||||
label.text = " %s°%s " % (temp, temp_unit)
|
||||
json_time = response_as_json['current_weather']['time']
|
||||
new_time = json_time.rsplit("T", 1)[-1]
|
||||
new_time = int(new_time[:2])
|
||||
print(new_time)
|
||||
clock = time.monotonic()
|
||||
# map color to temp range. colder temps are cool colors, warmer temps warm colors
|
||||
temp_color = simpleio.map_range(temp_int, min_temp, max_temp, 255, 0)
|
||||
# checks if it's day or night based on hour
|
||||
if new_time in range(daytime_min, daytime_max):
|
||||
img = day_images[weather]
|
||||
else:
|
||||
img = night_images[weather]
|
||||
# draw bitmap sprite
|
||||
for pixel in img:
|
||||
pixels[count] = pixel
|
||||
pixels.show()
|
||||
count+=1
|
||||
time.sleep(0.001)
|
||||
time.sleep(5)
|
||||
hue = 0
|
||||
count = 0
|
||||
# draw scrolling text
|
||||
for v in range(2):
|
||||
for i in range(bitmap.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 * bitmap[i,y]
|
||||
pixels.show()
|
||||
time.sleep(.1)
|
||||
191
NeoPixel_Sprite_Weather_Display/weather_codes.py
Normal file
191
NeoPixel_Sprite_Weather_Display/weather_codes.py
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
y = (255, 125, 0)
|
||||
o = (0, 0, 0)
|
||||
a = (0, 75, 125)
|
||||
w = (255, 255, 255)
|
||||
v = (127, 0, 255)
|
||||
b = (0, 0, 255)
|
||||
z = (0, 0, 25)
|
||||
g = (25, 25, 25)
|
||||
sun_bitmap = [
|
||||
y,a,y,a,y,
|
||||
a,y,y,y,a,
|
||||
y,y,y,y,y,
|
||||
a,y,y,y,a,
|
||||
y,a,y,a,y,
|
||||
]
|
||||
cloud_bitmap = [
|
||||
a,a,a,w,a,
|
||||
a,w,w,w,a,
|
||||
a,w,w,w,a,
|
||||
a,a,w,w,a,
|
||||
a,a,a,w,a,
|
||||
]
|
||||
partSun_bitmap = [
|
||||
a,w,w,w,a,
|
||||
a,w,w,w,w,
|
||||
y,y,w,w,a,
|
||||
a,y,y,w,a,
|
||||
y,a,y,a,a,
|
||||
]
|
||||
rain_bitmap = [
|
||||
z,z,v,z,b,
|
||||
v,v,v,b,z,
|
||||
v,v,v,z,b,
|
||||
z,v,v,b,z,
|
||||
z,z,v,z,b,
|
||||
]
|
||||
thunder_bitmap = [
|
||||
z,z,v,z,b,
|
||||
v,v,v,b,z,
|
||||
v,v,y,z,y,
|
||||
z,y,v,y,z,
|
||||
z,z,v,z,b,
|
||||
]
|
||||
snow_bitmap = [
|
||||
z,z,v,z,w,
|
||||
v,v,v,w,z,
|
||||
v,v,v,z,w,
|
||||
z,v,v,w,z,
|
||||
z,z,v,z,w,
|
||||
]
|
||||
night_bitmap = [
|
||||
y,g,g,y,g,
|
||||
g,g,y,g,g,
|
||||
g,y,g,g,y,
|
||||
y,y,y,g,g,
|
||||
g,y,g,g,g,
|
||||
]
|
||||
nightCloud_bitmap = [
|
||||
g,w,w,w,g,
|
||||
g,w,w,w,g,
|
||||
y,g,w,w,g,
|
||||
g,g,g,w,g,
|
||||
g,g,y,g,g,
|
||||
]
|
||||
nightRain_bitmap = [
|
||||
g,v,v,v,b,
|
||||
g,v,v,v,g,
|
||||
y,g,v,v,b,
|
||||
g,g,g,v,g,
|
||||
g,g,y,g,g,
|
||||
]
|
||||
nightThunder_bitmap = [
|
||||
g,v,v,v,b,
|
||||
g,v,v,v,g,
|
||||
g,g,y,v,y,
|
||||
v,y,g,y,b,
|
||||
v,v,b,g,g,
|
||||
]
|
||||
nightSnow_bitmap = [
|
||||
g,v,v,v,w,
|
||||
g,v,v,v,g,
|
||||
y,g,v,v,w,
|
||||
g,g,g,v,g,
|
||||
g,g,y,g,g,
|
||||
]
|
||||
|
||||
weather_codes = [
|
||||
{"code" : 0, "day_img" : sun_bitmap, "night_img" : night_bitmap},
|
||||
{"code" : 1, "day_img" : sun_bitmap, "night_img" : night_bitmap},
|
||||
{"code" : 2, "day_img" : sun_bitmap, "night_img" : night_bitmap},
|
||||
{"code" : 3, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 4, "day_img" : partSun_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 5, "day_img" : partSun_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 6, "day_img" : partSun_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 7, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 8, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 9, "day_img" : partSun_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 10, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 11, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 12, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 13, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 14, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 15, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 16, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 17, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 18, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 19, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 20, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 21, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 22, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 23, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 24, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 25, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 26, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 27, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 28, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 29, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 30, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 31, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 32, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 33, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 34, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 35, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 36, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 37, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 38, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 39, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 40, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 41, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 42, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 43, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 44, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 45, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 46, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 47, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 48, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 49, "day_img" : cloud_bitmap, "night_img" : nightCloud_bitmap},
|
||||
{"code" : 50, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 51, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 52, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 53, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 54, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 55, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 56, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 57, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 58, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 59, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 60, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 61, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 62, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 63, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 64, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 65, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 66, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 67, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 68, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 69, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 70, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 71, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 72, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 73, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 74, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 75, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 76, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 77, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 78, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 79, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 80, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 81, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 82, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 83, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 84, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 85, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 86, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 87, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 88, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 89, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 90, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 91, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 92, "day_img" : rain_bitmap, "night_img" : nightRain_bitmap},
|
||||
{"code" : 93, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 94, "day_img" : snow_bitmap, "night_img" : nightSnow_bitmap},
|
||||
{"code" : 95, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 96, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 97, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 98, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap},
|
||||
{"code" : 99, "day_img" : thunder_bitmap, "night_img" : nightThunder_bitmap}
|
||||
]
|
||||
Loading…
Reference in a new issue