Skip to content

Instantly share code, notes, and snippets.

@jfurcean
Last active January 21, 2021 01:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfurcean/dbf1608188c9fcfcf942c7489c22a3d0 to your computer and use it in GitHub Desktop.
Save jfurcean/dbf1608188c9fcfcf942c7489c22a3d0 to your computer and use it in GitHub Desktop.
Display COVID-19 Vaccine Data on a Adafruit MatrixPortal
# SPDX-FileCopyrightText: 2021 John Furcean
# SPDX-License-Identifier: MIT
import board
import busio
from digitalio import DigitalInOut
import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_bitmap_font import bitmap_font
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_display_text.label
import board
import displayio
import framebufferio
import rgbmatrix
import terminalio
import time
import neopixel
# Number of Seconds in an hour times the number of hours
# This dictates the data refresh time
TIME_THRESHOLD = 3600*4
# URL for the Our World in Data
# Our World in Data: https://ourworldindata.org/covid-vaccinations#source-information-country-by-country
# Raw Data URLs: https://github.com/owid/covid-19-data/tree/master/public/data/vaccinations
#
DATA_URL = "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/vaccinations/country_data/United%20States.csv"
POPULATION = 328200000
def fetch_data(URL):
'''
fetches data from Our World in Data via github
URL: a url of an github raw csv
Returns: dictionary of the data
'''
#Debugging print statements
print()
print("Fetching json from", URL)
r = requests.get(URL)
raw_data = r.text
r.close()
# split the raw csv data string into a list of lines
raw_data = raw_data.split('\n')
# remove blank last line
data = raw_data[:-1]
for i in range(1,len(data)):
# split each line of the csv into a list
data[i] = data[i].split(',')
data[i] = data[i][-3:]
# intialize output dictionary
vaccine_data = {}
vaccine_data['total'] = int(data[-1][1])
vaccine_data['last'] = int(data[-1][1]) - int(data[-2][1])
#vaccine_data['3-day-avg'] = int((int(data[-1][0]) - int(data[-3][0]))/3)
vaccine_data['percent'] = (vaccine_data['total']/POPULATION) * 100
if '"' in raw_data[-2]:
vaccine_data['types'] = raw_data[-2].split('"')[1]
else:
vaccine_data['types'] = raw_data[-2].split(',')[2]
return vaccine_data
def scroll(line):
line.x = line.x - 1
line_width = line.bounding_box[2]
if line.x < -line_width:
line.x = display.width
#initialize the RGB Matrix
displayio.release_displays()
matrix = rgbmatrix.RGBMatrix(
width=64, bit_depth=4,
rgb_pins=[
board.MTX_R1,
board.MTX_G1,
board.MTX_B1,
board.MTX_R2,
board.MTX_G2,
board.MTX_B2
],
addr_pins=[
board.MTX_ADDRA,
board.MTX_ADDRB,
board.MTX_ADDRC,
board.MTX_ADDRD
],
clock_pin=board.MTX_CLK,
latch_pin=board.MTX_LAT,
output_enable_pin=board.MTX_OE
)
display = framebufferio.FramebufferDisplay(matrix)
# Create two lines of text.
line1 = adafruit_display_text.label.Label(
terminalio.FONT,
color=0x00FF00,
text=f"VACCINE",
max_glyphs = 100)
line1.x = 2
line1.y = 6
line1.index = 0
line2 = adafruit_display_text.label.Label(
terminalio.FONT,
color=0xFFFFFF,
text=f"UPDATES",
max_glyphs=255)
line2.x = 2
line2.y = 20
line2.index= 0
# Put each line of text into a Group, then show that group.
g = displayio.Group()
g.append(line1)
g.append(line2)
display.show(g)
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
requests.set_socket(socket, esp)
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
# Boolean to force the initial data fetch
has_data = False
while True:
#Get the current time
now = time.monotonic()
# check if the current time has passed some threshold
# or if no data has been fetched
if not has_data or now - data_time > TIME_THRESHOLD:
print("Checking AP Connection...")
while not esp.is_connected:
try:
esp.connect_AP(secrets["ssid"], secrets["password"])
except RuntimeError as e:
print("could not connect to AP, retrying: ", e)
continue
line1.x = 2
line2.x = 2
line1.text = "Fetching"
line2.text = "Data..."
try:
#fetch the data of the United States
vaccine_data = fetch_data(DATA_URL)
temp_text = f"LAST RECORDED DAY: {vaccine_data['last']:,} "
#temp_text += f"3-DAY AVERAGE: {vaccine_data['3-day-avg']:,} "
temp_text += f"TOTAL: {vaccine_data['total']:,} "
temp_text += f"PERCENT: {vaccine_data['percent']:.2f}% "
temp_text += f"TYPES: {vaccine_data['types']} "
line1.text = 'VACCINATED'
line2.text = temp_text
#get time of data fetch
data_time = time.monotonic()
has_data = True
except RuntimeError as e:
print("Couldn't fetch data!")
continue
#scroll the two lines
scroll(line2)
time.sleep(.04)
display.refresh(minimum_frames_per_second=0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment