Last active
January 21, 2021 01:27
-
-
Save jfurcean/dbf1608188c9fcfcf942c7489c22a3d0 to your computer and use it in GitHub Desktop.
Display COVID-19 Vaccine Data on a Adafruit MatrixPortal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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