Skip to content

Instantly share code, notes, and snippets.

@jameseleach
Last active December 3, 2020 14:04
Show Gist options
  • Save jameseleach/d2b48b37166ba2d1196875a46a252ef2 to your computer and use it in GitHub Desktop.
Save jameseleach/d2b48b37166ba2d1196875a46a252ef2 to your computer and use it in GitHub Desktop.
MatrixPortal Clock and Weather
from time import localtime, monotonic
from json import loads
from board import SCL, SDA, NEOPIXEL, A0
from busio import I2C
from neopixel import NeoPixel
from displayio import Group, Bitmap, Palette, TileGrid
from adafruit_vcnl4040 import VCNL4040
from adafruit_imageload import load
from adafruit_display_text.label import Label
from adafruit_bitmap_font.bitmap_font import load_font
from adafruit_matrixportal.network import Network
from adafruit_matrixportal.matrix import Matrix
from reshader import Reshader
from secrets import secrets
# Probably don't modify these values
CB = 0.5
LTU = None
LWU = None
LDS = None
class Weather:
def __init__(self, i, t, d, h, l):
self.icon = i
self.temp = t
self.description = d
self.high_temp = h
self.low_temp = l
def capitalize(s):
return " ".join([word[0].upper() + word[1:] for word in s.split()])
def get_formatted_time(): # Format the current time as HH:MM
now = localtime()
hours = now.tm_hour
if hours > 12:
hours -= 12
if hours == 0:
hours = 12
minutes = now.tm_min
return "{hours}:{minutes:02d}".format(hours=hours, minutes=minutes)
def update_time_display():
text = get_formatted_time()
previous_text = clock_label.text
if text != previous_text:
clock_label.text = text
clock_label.x = round(display.width / 2 - clock_label.bounding_box[2] / 2) - 1
def query_weather(): # Query weather from API
ws =('https://api.openweathermap.org/data/2.5/weather?id=' + secrets['location_id'] + '&appid=' + secrets['openweather_token'] + '&units=imperial')
fs = ('https://api.openweathermap.org/data/2.5/forecast?lat=' + secrets['latitude'] + '&lon=' + secrets['longitude'] + '&appid=' + secrets['openweather_token'] + '&units=imperial&cnt=4')
wir = {"01d": 0,"01n": 1,"02d": 2,"02n": 3,"03d": 4,"03n": 5,"04d": 6,"04n": 7,"09d": 8,"09n": 9,"10d": 10,"10n": 11,"11d": 12,"11n": 13,"13d": 14,"13n": 15,"50d": 16,"50n": 17}
c = loads(network.fetch_data(ws))
f = loads(network.fetch_data(fs))
temps = [i['main']['temp'] for i in f['list']]
temps.append(c["main"]["temp"])
return Weather(wir[c["weather"][0]["icon"]], '{:.0f}'.format(c["main"]["temp"]), capitalize(c["weather"][0]["description"]), '{:.0f}'.format(max(temps)), '{:.0f}'.format(min(temps)))
def update_weather_display():
if results.icon != weather_icon[0]:
weather_icon[0] = results.icon
if results.temp != temp_label.text:
temp_label.text = results.temp
temp_label.x = (round(32 / 2 - temp_label.bounding_box[2] / 2) - 1) + 16
if results.description != desc_label.text:
desc_label.text = results.description
desc_label.x = round(display.width / 2 - desc_label.bounding_box[2] / 2) - 1
if results.high_temp != hi_temp_label.text:
hi_temp_label.text = results.high_temp
hi_temp_label.x = display.width - hi_temp_label.bounding_box[2]
if results.low_temp != lo_temp_label.text:
lo_temp_label.text = results.low_temp
lo_temp_label.x = display.width - lo_temp_label.bounding_box[2]
def update_display():
if clock_group.hidden:
update_weather_display()
else:
update_time_display()
def switch_display():
if clock_group.hidden:
weather_group.hidden = True
clock_group.hidden = False
else:
clock_group.hidden = True
weather_group.hidden = False
def adjust_brightness(l, cb):
if l < 20:
v = 0.1
elif l > 70:
v = 1.0
else:
v = 0.5
if v != cb:
icon_shader.reshade(v)
clock_label_shader.reshade(v)
temp_label_shader.reshade(v)
desc_label_shader.reshade(v)
hi_temp_label_shader.reshade(v)
lo_temp_label_shader.reshade(v)
return v
# Setup VCNL4040 sensor
i2c = I2C(SCL, SDA)
sensor = VCNL4040(i2c)
# --- Turn off on-board Neopixel
pixel = NeoPixel(NEOPIXEL, 1)
pixel.fill((0,0,0))
# Display setup
matrix = Matrix(width=64, height=32, bit_depth=6)
display = matrix.display
network = Network()
# Main screen setup
main_group = Group(max_size=2) # The Main Display Group
display.show(main_group)
# Setup Clock Group
clock_group = Group(max_size=1)
clock_font = load_font("fonts/Noto-18.bdf")
# clock_font.load_glyphs(b'0123456780:')
clock_label = Label(clock_font, color=0xFF0000, max_glyphs=5, y=display.height // 2)
clock_label.text = "wait"
clock_label.x = round(display.width / 2 - clock_label.bounding_box[2] / 2) - 1
clock_label_shader = Reshader(clock_label.palette)
clock_group.append(clock_label)
# Add the clock group to the main group
main_group.append(clock_group)
# Setup Weather Group
weather_group = Group(max_size=6, scale=1)
icon, icon_palette = load("gfx/w-icons.bmp", bitmap=Bitmap, palette=Palette)
weather_icon = TileGrid(icon,pixel_shader=icon_palette,width=1,height=1,tile_width=16,tile_height=16,default_tile=5,x=0,y=0)
icon_shader = Reshader(icon_palette)
a12_font = load_font("fonts/Arial-12.bdf")
#a12_font.load_glyphs(b'1234567890 °FC')
temp_label = Label(a12_font, color=0xFF00FF, x=18, y=8, max_glyphs=8)
temp_label.text = "999"
temp_label.x = (round(32 / 2 - temp_label.bounding_box[2] / 2) - 1) + 16
temp_label_shader = Reshader(temp_label.palette)
f58_font = load_font("fonts/5x8.bdf")
#f58_font.load_glyphs(b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ')
desc_label = Label(f58_font, color=0x00FFFF, x=0, y=16+8, max_glyphs=16)
desc_label.text = "Unknown"
desc_label.x = round(display.width / 2 - desc_label.bounding_box[2] / 2) - 1
desc_label_shader = Reshader(desc_label.palette)
hi_temp_label = Label(f58_font, color=0xFF0000, x=48, y=2, max_glyphs=6)
hi_temp_label.text = "999"
hi_temp_label.x = display.width - hi_temp_label.bounding_box[2]
hi_temp_label_shader = Reshader(hi_temp_label.palette)
lo_temp_label = Label(f58_font, color=0x00FFFF, x=48, y=10, max_glyphs=6)
lo_temp_label.text = "-99"
lo_temp_label.x = display.width - lo_temp_label.bounding_box[2]
lo_temp_label_shader = Reshader(lo_temp_label.palette)
weather_group.append(weather_icon)
weather_group.append(temp_label)
weather_group.append(desc_label)
weather_group.append(hi_temp_label)
weather_group.append(lo_temp_label)
# Add weather group to main group and hide.
main_group.append(weather_group)
weather_group.hidden = True
while True:
if LTU is None or monotonic() > LTU + 3600:
try:
network.get_local_time()
LTU = monotonic()
#update_time_display()
except RuntimeError as e:
print("Error when querying -", e)
if LWU is None or monotonic() > LWU + 3600:
try:
results = query_weather()
LWU = monotonic()
#update_weather_display()
except RuntimeError as e:
print("Error when querying weather. -", e)
CB = adjust_brightness(sensor.lux, CB)
if sensor.proximity > 20 and (LDS is None or monotonic() > LDS + 5):
print("You're close!")
switch_display()
LDS = monotonic()
if clock_group.hidden and monotonic() > LDS + 10:
print("Weather screen timeout.")
switch_display()
LDS = monotonic()
update_display()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment