class Inkywhatrbw(Observer): def __init__(self, observable, mode): super().__init__(observable=observable) self.inky_display = InkyWHAT("red") self.inky_display.set_border(self.inky_display.WHITE) self.image = Image.new('P', (SCREEN_WIDTH, SCREEN_HEIGHT)) self.mode = mode def form_image(self, prices): WHITE = self.inky_display.WHITE RED = self.inky_display.RED BLACK = self.inky_display.BLACK screen_draw = ImageDraw.Draw(self.image) screen_draw.rectangle([0,0,SCREEN_WIDTH,SCREEN_HEIGHT],fill=WHITE) if self.mode == "candle": Plot.candle(prices, size=(SCREEN_WIDTH - LEFT_MARGIN, SCREEN_HEIGHT - BOTTOM_MARGIN), position=(LEFT_MARGIN, 0), draw=screen_draw, fill_neg=RED, fill_pos=BLACK) else: last_prices = [x[3] for x in prices] Plot.line(last_prices, size=(SCREEN_WIDTH - LEFT_MARGIN, SCREEN_HEIGHT - BOTTOM_MARGIN), position=(LEFT_MARGIN, 0), draw=screen_draw, fill=BLACK) flatten_prices = [item for sublist in prices for item in sublist] Plot.y_axis_labels(flatten_prices, FONT_SMALL, (0, 0), (LEFT_MARGIN, SCREEN_HEIGHT - BOTTOM_MARGIN - SMALL_FONT_SIZE - 3), draw=screen_draw, fill=BLACK) screen_draw.line([(0, SCREEN_HEIGHT - BOTTOM_MARGIN), (SCREEN_WIDTH, SCREEN_HEIGHT - BOTTOM_MARGIN)], fill=BLACK) screen_draw.line([(LEFT_MARGIN, 0), (LEFT_MARGIN, SCREEN_HEIGHT - BOTTOM_MARGIN)], fill=BLACK) Plot.caption(flatten_prices[len(flatten_prices) - 1], SCREEN_HEIGHT - BOTTOM_MARGIN, SCREEN_WIDTH, FONT_LARGE, screen_draw, fill=BLACK, currency_offset=LEFT_MARGIN, price_offset=LEFT_MARGIN) def update(self, data): self.form_image(data) self.inky_display.set_image(self.image) self.inky_display.show() def close(self): pass
def try_real_hw(): try: from inky import InkyWHAT inky_display = InkyWHAT('red') inky_display.set_border(inky_display.WHITE) return inky_display except ImportError: return None
def inky_show(im): im = Image.open(im) im = im.transpose(Image.ROTATE_90) inky_display = InkyWHAT("black") inky_display.set_border(inky_display.WHITE) assert inky_display.WIDTH == 400 assert inky_display.HEIGHT == 300 inky_display.set_image(im) inky_display.show()
def setup_inky(inky_colour): from inky import InkyWHAT inky_display = InkyWHAT(inky_colour) ink_white = inky_display.WHITE #0 ink_black = inky_display.BLACK #1 ink_color = inky_display.YELLOW #2 inky_display.set_border(inky_display.WHITE) w = inky_display.WIDTH h = inky_display.HEIGHT return w, h, ink_black, ink_color #,fonts_dict
def send_to_display(): # TODO: do only in python... was having some issues with svg2png output_svg_path = os.path.abspath("output.svg") output_png_path = os.path.abspath("output.png") os.system( f"inkscape -z -w 400 -h 300 {output_svg_path} -e {output_png_path}") img = Image.open(output_png_path) pal_img = Image.new("P", (1, 1)) pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252) img = img.convert("RGB").quantize(palette=pal_img) # send inky_display = InkyWHAT("red") inky_display.set_border(inky_display.RED) inky_display.set_image(img) inky_display.show()
def glyphe(): # Load the icons and rotate them each time. This gives us # a horoscope which rotates during the day, potentially # making us think differently about their meaning print("Starting...") icons = pickle.load( open( "glyphes.pickle", "rb" ) ) print(icons) icons.insert(0, icons.pop()) # put the last element at the front pickle.dump( icons, open( "glyphes.pickle", "wb" ) ) print(icons) total_width = 1947 # to make this 400/300 on resize total_height = 1460 # 2 * 700 + 60 new_image = Image.new('RGBA', (total_width, total_height), 255) offset = ( int(total_width / 2) - 700, 30) new_image.paste( Image.open(dir + 'icons/' + str(icons[0])), offset ) offset = ( int(total_width / 2), 30 ) new_image.paste( Image.open(dir + 'icons/' + icons[1]), offset ) offset = ( int(total_width / 2) - 700, int(new_image.height / 2) + 10) new_image.paste( Image.open(dir + 'icons/' + icons[2]), offset ) offset = ( int(new_image.width / 2), int(new_image.height / 2) + 10 ) new_image.paste( Image.open(dir + 'icons/' + icons[3]), offset ) new_image.convert('P') new_image.save(dir + 'saved/glyphe.png') # Now resize the image to 400x300 and save it for eink display img = Image.open(dir + 'saved/glyphe.png') img = img.resize((400, 300), resample=Image.LANCZOS) img = img.quantize() img.save(dir + 'saved/glyphe-resized.png') from inky import InkyWHAT inky_display = InkyWHAT("black") inky_display.set_border(inky_display.WHITE) inky_display.set_image(img) inky_display.show() print("Done!")
def create(quote): inky_display = InkyWHAT("black") inky_display.set_border(inky_display.WHITE) # From https://gist.github.com/jasondilworth56/27764ae8ed2327a34ceebb06e75c30ea from PIL import ImageFont, ImageDraw, Image text = quote[0] author = quote[1] title = quote[2] #font = "/usr/share/fonts/truetype/freefont/FreeMono.ttf" font = "/usr/share/fonts/truetype/freefont/FreeSans.ttf" #font = "/home/pi/.fonts/Roboto-Bold.ttf" #font = "/home/pi/.fonts/Bitter-Regular.otf" #font = "/home/pi/.fonts/ufonts.com_rockwell.ttf" #font = "/home/pi/.fonts/Bookerly/Bookerly-Regular.ttf" #font = "/home/pi/.fonts/static/PlayfairDisplay-Regular.ttf" #font = "/home/pi/.fonts/PlayfairDisplay-VariableFont_wght.ttf" font = "/home/pi/.fonts/FredokaOne-Regular.ttf" #font = "/home/pi/.fonts/AmaticSC-Regular.ttf" img = ImageText((400, 300), background=(255, 255, 255)) img.fill_text_box((20, 20), text, box_width=340, box_height=250, font_filename=font) meta_line = author + ', ' + title #img.write_text( (10, inky_display.HEIGHT - 20), meta_line, font_filename=font) #img.fill_text_box((30, inky_display.HEIGHT - 40), meta_line, box_width=320, box_height=30, font_filename=font) img.write_text_box((30, inky_display.HEIGHT - 30), meta_line, box_width=320, font_filename=font, font_size=12, place='right') filename = '/home/pi/src/coten/images/coten.png' img.save(filename) img = Image.open(filename) img = img.quantize() inky_display.set_image(img) inky_display.set_border(inky_display.WHITE) inky_display.show()
updateTextWidth, updateTextHeight = accountFont.getsize(tweet_update) draw.text( ((displayWidth - updateTextWidth), (headerHeight - updateTextHeight)), tweet_update, white, updateFont) ######################## ## FINALISE THE IMAGE ## ######################## # Set a PIL image, numpy array or list to Inky's internal buffer. The image dimensions should match the dimensions of the pHAT or wHAT you're using. # You should use PIL to create an image. PIL provides an ImageDraw module which allow you to draw text, lines and shapes over your image. # See: https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html inky.set_image(img) ############################### ## SET DISPLAY BORDER COLOUR ## ############################### # .set_border(colour) sets the colour at the edge of the display # colour should be one of 'inky.RED', 'inky.YELLOW', 'inky.WHITE' or 'inky.BLACK' with available colours depending on your display type. inky.set_border(white) ######################## ## UPDATE THE DISPLAY ## ######################## # Once you've prepared and set your image, and chosen a border colour, you can update your e-ink display with .show() if test == True: img.save("debug.png") else: inky.show()
from math import floor from random import randint from inky import InkyWHAT from PIL import Image, ImageDraw inky_display = InkyWHAT("red") inky_display.set_border(inky_display.WHITE) rules = [18, 22, 26, 30, 45, 57, 60, 62, 73, 75, 82, 86, 89, 90, 101, 102, 105, 109, 110, 124, 126, 129, 131, 135, 137, 145, 146, 149, 150, 153, 154, 161, 165, 167, 181, 182, 190, 193, 195, 210, 214, 218, 225] rulesetNo = rules[randint(0, len(rules) - 1)] ruleset = list(map(int, bin(rulesetNo)[2:].zfill(8)[::-1])) for i in range(0, 8): if ruleset[i] == 1: if randint(0, 100) <= 25: ruleset[i] = 2 print(ruleset) width = inky_display.WIDTH height = inky_display.HEIGHT cellSize = randint(1, 5) rectSize = cellSize - 1 visibleGenerations = floor(height / cellSize) numCells = floor(width / cellSize) cells = [0] * numCells
parser.add_argument("--write", action="store_true", default=False) parser.add_argument("--border", action="store_true", default=False) parser.add_argument("--font", default="Gidole-Regular") parser.add_argument("--font-size", type=int, default=25) parser.add_argument("--font-padding", type=int, default=5) parser.add_argument("--filename", type=str, help="resources/matisse.png|promenade_des_anglais.jpg") args = parser.parse_args() logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO) inky_display = InkyWHAT("black") if args.border: inky_display.set_border(inky_display.BLACK) if args.clear: logging.info("Clearing Inky") clear(inky_display) if args.draw and args.filename: logging.info(f"Drawing Inky {args.filename}") image = prepare(inky_display, args.filename) draw(inky_display, image) if args.write: logging.info(f"Writing Inky lines from stdin") font = ImageFont.truetype(args.font, args.font_size) # font = ImageFont.truetype(FredokaOne, args.font_size) lines = fit_lines(
#make the image - commented for LED #img = qr.make_image(fill_color="orange", back_color="purple") img = qr.make_image(fill_color="black", back_color="white") #save as a file img.save('qr_image.png') imgURL = "./displayScreens/qrscan_bw.png" im = Image.open(imgURL) #resizing the image so it fits to the screen adding RGB support size = (400, 300) out = im.resize(size) out.save('resize-output.png') #combine the images, note: must have ImageMagick installed on pi subprocess.call( 'composite -blend 100 -gravity center qr_image.png resize-output.png displayImage.png', shell=True) print("Merged images") img = Image.open('displayImage.png') pal_img = Image.new("P", (1, 1)) pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252) img = img.convert("RGB").quantize(palette=pal_img) inkywhat.set_image(img) #NOTE can only have this line on a rasberry pi inkywhat.set_border('white') inkywhat.show()
def create_pimoroni(quote): import argparse import random import sys from inky import InkyWHAT from PIL import Image, ImageFont, ImageDraw from font_source_serif_pro import SourceSerifProSemibold from font_source_sans_pro import SourceSansProSemibold # Set up the correct display and scaling factors inky_display = InkyWHAT('black') inky_display.set_border(inky_display.WHITE) # inky_display.set_rotation(180) w = inky_display.WIDTH h = inky_display.HEIGHT # Create a new canvas to draw on img = Image.new("P", (inky_display.WIDTH, inky_display.HEIGHT)) draw = ImageDraw.Draw(img) # Load the fonts font_size = 24 author_font_size = 18 quote_font = ImageFont.truetype(SourceSansProSemibold, font_size) author_font = ImageFont.truetype(SourceSerifProSemibold, author_font_size) # The amount of padding around the quote. Note that # a value of 30 means 15 pixels padding left and 15 # pixels padding right. # # Also define the max width and height for the quote. padding = 50 max_width = w - padding max_height = h - padding - author_font.getsize("ABCD ")[1] below_max_length = False # Only pick a quote that will fit in our defined area # once rendered in the font and size defined. while not below_max_length: reflowed = reflow_quote(quote, max_width, quote_font) p_w, p_h = quote_font.getsize(reflowed) # Width and height of quote p_h = p_h * (reflowed.count("\n") + 1) # Multiply through by number of lines if p_h < max_height: below_max_length = True # The quote fits! Break out of the loop. else: font_size = font_size - 1 author_font_size = author_font_size - 1 quote_font = ImageFont.truetype(SourceSansProSemibold, font_size) author_font = ImageFont.truetype(SourceSerifProSemibold, author_font_size) continue # x- and y-coordinates for the top left of the quote quote_x = (w - max_width) / 2 quote_y = ((h - max_height) + (max_height - p_h - author_font.getsize("ABCD ")[1])) / 2 # x- and y-coordinates for the top left of the author author_x = quote_x author_y = quote_y + p_h author = [ '— ' + quote[1] + ', ' + quote[2] ] reflowed_author = reflow_quote(author, max_width, author_font) # Write our quote and author to the canvas draw.multiline_text((quote_x, quote_y), reflowed, fill=inky_display.BLACK, font=quote_font, align="left") draw.multiline_text((author_x, author_y), reflowed_author, fill=inky_display.BLACK, font=author_font, align="right") print(reflowed + "\n" + reflowed_author + "\n") # Display the completed canvas on Inky wHAT inky_display.set_image(img) inky_display.show()
def on_message(mosq, obj, msg): # Set MQTT Message message = str(msg.payload.decode('UTF-8')) print(message) # Set Font etc and Refresh inky_display = InkyWHAT("red") inky_display.set_border(inky_display.WHITE) img = Image.open("/home/pi/scripts/resources/whatbackground.png" ) #adds a red line at the bottom draw = ImageDraw.Draw(img) # Display the completed canvas on Inky wHAT if 'Weather' in message: fonttop = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 30) # any ttf font can be used font = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 30) # any ttf font can be used wrapped = textwrap.wrap(message, width=24) if (len(wrapped) >= 1): # Status Line 1 status_one = wrapped[0] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 10 - (h / 2) draw.text((15, 30), status_one, inky_display.RED, fonttop, align="left") if (len(wrapped) >= 2): # Status Line 2 status_two = wrapped[1] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 35 - (h / 2) draw.text((15, 70), status_two, inky_display.BLACK, font, align="left") if (len(wrapped) >= 3): # Status Line 3 status_three = wrapped[2] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 60 - (h / 2) draw.text((15, 110), status_three, inky_display.BLACK, font, align="left") if (len(wrapped) >= 4): # Status Line 4 status_four = wrapped[3] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 150), status_four, inky_display.BLACK, font, align="left") if (len(wrapped) >= 5): # Status Line 5 status_five = wrapped[4] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 190), status_five, inky_display.BLACK, font, align="left") if (len(wrapped) >= 6): # Status Line 5 status_six = wrapped[5] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 230), status_six, inky_display.BLACK, font, align="left") elif 'Time' in message: fonttop = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 50) # larger text for time font = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 50) # larger text for time wrapped = textwrap.wrap(message, width=14) if (len(wrapped) >= 1): # Status Line 1 status_one = wrapped[0] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 10 - (h / 2) draw.text((15, 40), status_one, inky_display.RED, fonttop, align="left") if (len(wrapped) >= 2): # Status Line 2 status_two = wrapped[1] w, h = font.getsize(status_two) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 35 - (h / 2) draw.text((15, 100), status_two, inky_display.BLACK, font, align="left") if (len(wrapped) >= 3): # Status Line 3 status_three = wrapped[2] w, h = font.getsize(status_three) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 60 - (h / 2) draw.text((15, 160), status_three, inky_display.BLACK, font, align="left") if (len(wrapped) >= 4): # Status Line 4 status_four = wrapped[3] w, h = font.getsize(status_four) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 220), status_four, inky_display.BLACK, font, align="left") else: fonttop = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 24) font = ImageFont.truetype("/home/pi/scripts/resources/hm.ttf", 26) wrapped = textwrap.wrap(message, width=27.5) if (len(wrapped) >= 1): # Status Line 1 status_one = wrapped[0] w, h = font.getsize(status_one) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 10 - (h / 2) draw.text((15, 10), status_one, inky_display.RED, fonttop, align="left") if (len(wrapped) >= 2): # Status Line 2 status_two = wrapped[1] w, h = font.getsize(status_two) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 35 - (h / 2) draw.text((15, 50), status_two, inky_display.BLACK, font, align="left") if (len(wrapped) >= 3): # Status Line 3 status_three = wrapped[2] w, h = font.getsize(status_three) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 60 - (h / 2) draw.text((15, 90), status_three, inky_display.BLACK, font, align="left") if (len(wrapped) >= 4): # Status Line 4 status_four = wrapped[3] w, h = font.getsize(status_four) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 130), status_four, inky_display.BLACK, font, align="left") if (len(wrapped) >= 5): # Status Line 5 status_five = wrapped[4] w, h = font.getsize(status_five) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 170), status_five, inky_display.BLACK, font, align="left") if (len(wrapped) >= 6): # Status Line 5 status_six = wrapped[5] w, h = font.getsize(status_six) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 210), status_six, inky_display.BLACK, font, align="left") if (len(wrapped) >= 7): # Status Line 5 status_seven = wrapped[6] w, h = font.getsize(status_seven) # Center the text and align it with the name strip x = (inky_display.WIDTH / 2) - (w / 2) y = 85 - (h / 2) draw.text((15, 250), status_seven, inky_display.BLACK, font, align="left") # Display the completed canvas on Inky wHAT inky_display.set_image(img) inky_display.show() print(message)
api_key = "<your API key>" if (api_key == "<your API key>"): print("You forgot to enter your API key") exit() lat = "52.988040" lon = "8.866697" url = "https://api.openweathermap.org/data/2.5/onecall?lat=%s&lon=%s&exclude=hourly&appid=%s&units=metric" % ( lat, lon, api_key) tile_positions = [] for i in range(2): for j in range(4): tile_positions.append((j * TILE_WIDTH, i * TILE_HEIGHT)) inky_display = InkyWHAT("red") inky_display.set_border(inky_display.RED) font = ImageFont.truetype("fonts/BungeeColor-Regular_colr_Windows.ttf", FONT_SIZE) old_days = [] while (True): try: response = requests.get(url) data = json.loads(response.text) except: None days = [] daily = data["daily"]
def update_inky(): raw = get_today() data = build_today(raw) print(data) # INIT # ==== inky = InkyWHAT("yellow") inky.set_border(inky.BLACK) # initiate image img = Image.new("P", (inky.WIDTH, inky.HEIGHT)) draw = ImageDraw.Draw(img) # HEADER # ====== # add name x = "WFH" font = build_font(20) w, h = get_font_size(font, x) draw.text((X_EDGE, Y_EDGE), x, inky.YELLOW, font) # add date now = data["now"] date_str = now.strftime("%d.%m.%Y") wd, _ = get_font_size(font, date_str) time_str = now.strftime("%H:%M") wt, _ = get_font_size(font, time_str) draw.text((inky.WIDTH - wt - wd - X_EDGE, Y_EDGE), date_str, inky.BLACK, font) draw.text((inky.WIDTH - wt, Y_EDGE), time_str, inky.YELLOW, font) # add divider HEADER_HEIGHT = h + Y_EDGE draw.line( (X_EDGE, HEADER_HEIGHT + 2, inky.WIDTH - X_EDGE, HEADER_HEIGHT + 2), fill=inky.BLACK, width=DIVIDER_HEIGHT) # FOOTER # ====== TIME_END = inky.WIDTH - 2 * X_EDGE dx = (TIME_END - X_LABEL) // len(TIMES) x = X_LABEL + X_EDGE y = inky.HEIGHT - ICON_SIZE * 1.5 # determine absolute start/end time (for referencing) TIME_START = x + (dx + ICON_SIZE) // 2 TIME_END -= ICON_SIZE // 2 - X_EDGE # add ENTIRE time bar draw.line((TIME_START, y, TIME_END, y), fill=inky.BLACK, width=DIVIDER_HEIGHT) # add icons for k, v in TIMES.items(): icon = load_image(v, ICON_SIZE) # add icons img.paste(icon, box=(x + dx // 2, inky.HEIGHT - ICON_SIZE - 2 * Y_EDGE)) # add MAJOR time ticks draw.line((x + (dx + ICON_SIZE) // 2, y + TICK_HEIGHT, x + (dx + ICON_SIZE) // 2, y - TICK_HEIGHT), fill=inky.BLACK, width=int(1.25 * DIVIDER_HEIGHT)) # add MINOR time ticks draw.line((x + dx + ICON_SIZE // 2, y + TICK_HEIGHT, x + dx + ICON_SIZE // 2, y - TICK_HEIGHT), fill=inky.BLACK, width=int(0.75 * DIVIDER_HEIGHT)) x += dx now_px = _convert_time(data["now"], TIME_START, TIME_END) draw.line((now_px, y + TICK_HEIGHT, now_px, y - TICK_HEIGHT), fill=inky.YELLOW, width=int(1.25 * DIVIDER_HEIGHT)) # WORK # ==== Y = 60 # add label label = "Work" font = build_font(30) w, h = get_font_size(font, label[0]) draw.text((X_EDGE + w, Y - h // 2), label[1:], inky.BLACK, font) draw.text((X_EDGE, Y - h // 2), label[0], inky.YELLOW, font) # fix logoff if not existing if len(data["login"]) != len(data["logoff"]): data["logoff"].append(data["now"]) working_times = list(zip(data["login"], data["logoff"])) total_sec = 0 font = build_font(18) for working_time in working_times: # start start_px = _convert_time(working_time[0], TIME_START, TIME_END) start_str = working_time[0].strftime("%H:%M") draw.text((start_px, Y + 4), start_str, inky.BLACK, font) # end stop_px = _convert_time(working_time[1], TIME_START, TIME_END) if (stop_px - start_px) > 100: stop_str = working_time[1].strftime("%H:%M") w, h = get_font_size(font, stop_str) draw.text((stop_px - int(0.75 * w), Y + 4), stop_str, inky.BLACK, font) # total total_sec += (working_time[1] - working_time[0]).total_seconds() # add time bar for working time draw.line((start_px, Y, stop_px, Y), fill=inky.YELLOW, width=3 * DIVIDER_HEIGHT) # write total work time total_str = "Σ {:.2f} hr".format(total_sec / 3600) font = build_font(25) w, h = get_font_size(font, total_str) draw.text((inky.WIDTH - w - X_EDGE, HEADER_HEIGHT + 5), total_str, inky.YELLOW, font) # FOOD # ==== Y = 128 # add label label = "Food" font = build_font(30) w, h = get_font_size(font, label[0]) draw.text((2 * X_EDGE + w // 3, Y - h // 2), label[1:], inky.BLACK, font) draw.text((X_EDGE, Y - h // 2), label[0], inky.YELLOW, font) # add lunch icon if data["lunch"]: icon = load_image(ICONS["lunch"], int(ICON_SIZE * .75)) lunch_px = _convert_time(data["lunch"][0], TIME_START, TIME_END) # ASSUME SINGLE LUNCH img.paste(icon, box=(lunch_px, Y - ICON_SIZE)) # add coffee icons for coffee in data["coffee"]: icon = load_image(ICONS["coffee"], ICON_SIZE) coffee_px = _convert_time(coffee, TIME_START, TIME_END) img.paste(icon, box=(coffee_px - ICON_SIZE // 2, Y + ICON_SIZE // 3)) # HEALTH # ====== Y = 205 # add label label = "Health" font = build_font(30) w, h = get_font_size(font, label[0]) draw.text((X_EDGE + w, Y - h // 2), label[1:], inky.BLACK, font) draw.text((X_EDGE, Y - h // 2), label[0], inky.YELLOW, font) # add pushup icons for pushups in data["pushups"]: icon = load_image(ICONS["pushups"], ICON_SIZE) pushups_px = _convert_time(pushups, TIME_START, TIME_END) img.paste(icon, box=(pushups_px - ICON_SIZE // 2, Y - ICON_SIZE)) # add move icons for move in data["move"]: icon = load_image(ICONS["move"], ICON_SIZE) move_px = _convert_time(move, TIME_START, TIME_END) img.paste(icon, box=(move_px - ICON_SIZE // 2, Y + ICON_SIZE // 3)) # set image to inky inky.set_image(img) inky.show()
def changeScreens(cardID): """Changes the screen shown on the Raspberry Pi Hat. Checks to see if the card is in the database and displays the corresponding screen. We are using the inkywHAT Red/Black/White: https://shop.pimoroni.com/products/inky-what?variant=13590497624147 Documentation: https://github.com/pimoroni/inky TODO: Change the screen back to "please scan card" after a set amount of time has passed. Needs some multithreading or something to accomplish that I think. """ ######## Pi Hat Setup ######## print("Changing screens...") inkywhat = InkyWHAT('black') # Establish a new connection for checking if the card is in the DB. # Not sure if this is required, but this is the easiest way I could find to do it. # Copy-pasted from the earlier mqtt_connection variable. pi_hat_connection = mqtt_connection_builder.mtls_from_path( endpoint=args.endpoint, cert_filepath=args.cert, pri_key_filepath=args.key, client_bootstrap=client_bootstrap, ca_filepath=args.root_ca, client_id=args.client_id, clean_session=False, keep_alive_secs=6) # Query the DB to see if that card is in it. # Use the config defined at the top of the file to hide connection information. cardInDBResult = False try: mysqlConn = mysql.connector.connect(host=config['database']['dbHostname'], database=config['database']['dbName'], user=config['database']['dbUsername'], password=config['database']['dbPassword']) if mysqlConn.is_connected(): print("Connected to database...") cursor = mysqlConn.cursor() cursor.execute("select database();") record = cursor.fetchone() lookForCardQuery = "SELECT * FROM Student_ID WHERE SID = " + str(cardID) cursor.execute(lookForCardQuery) records = cursor.fetchall() if(cursor.rowcount > 0): cardInDBResult = True except Error as e: print("Error while connecting to MySQL Database", e) finally: if (mysqlConn.is_connected()): cursor.close() mysqlConn.close() print("Disconnected from database...") # If the card is in the database, set the screen to be shown to the "Welcome" screen if (cardInDBResult): print("ID Found - Displaying Welcome...") imgURL = "../../../qrcode/displayScreens/welcome_bw.png" im = Image.open(imgURL) # Resizing the image so it fits to the screen # This is specific to the inkywhat, otherwise it claims that there is a size-mismatch. size = (400,300) out = im.resize(size) out.save('../../../qrcode/resize-output.png') img = Image.open('../../../qrcode/resize-output.png') pal_img = Image.new("P", (1, 1)) pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252) img = img.convert("RGB").quantize(palette=pal_img) # If the card is not in the database, make a QR code and show the "QR Code" screen elif (not cardInDBResult): print("ID Not Found - Displaying Registration...") imgURL = "../../../qrcode/displayScreens/qrscan_bw.png" displayURL = "../../../qrcode/qrCodeScreenMerged.png" # Generate a QR Code Object qr = qrcode.QRCode( version=None, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=3, border=2, ) # Generate the URL the code points to and add it to the QR Code wURL = config['aws_endpoints']['registrationSite'] + str(cardID) qr.add_data(wURL) qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") # Save the generated QR Code to the proper folder img.save('../../../qrcode/qr_image.png') im = Image.open(imgURL) # Resizing the image so it fits to the screen size = (400,300) out = im.resize(size) out.save('../../../qrcode/resize-output.png') # We are using ImageMagick installed on the Raspberry Pi to # composite our generated QR Code onto the premade image # with this subprocess call. This could be changed to a # bash script called in the same way. s = pyshorteners.Shortener(Shorteners.TINYURL) shortLink = s.short(wURL) composeQRCodeOntoImageCommand = 'composite -blend 100 -gravity center ../../../qrcode/qr_image.png ../../../qrcode/resize-output.png ../../../qrcode/qrCodeScreenMerged.png' composeURLOntoImageCommand = 'convert ../../../qrcode/qrCodeScreenMerged.png -gravity North -pointsize 24 -annotate +0+215 \'' + shortLink + '\' ../../../qrcode/qrCodeScreenMerged.png' subprocess.call(composeQRCodeOntoImageCommand, shell=True) subprocess.call(composeURLOntoImageCommand, shell=True) img = Image.open(displayURL) # Continue resizing, inkywhat complains otherwise. pal_img = Image.new("P", (1, 1)) pal_img.putpalette((255, 255, 255, 0, 0, 0, 255, 0, 0) + (0, 0, 0) * 252) img = img.convert("RGB").quantize(palette=pal_img) # Update the image on the screen and show it. inkywhat.set_image(img) inkywhat.set_border('white') inkywhat.show() print("Finished changing screens...")