# Copyright (C) 2020 Fintic, finticofficial@gmail.com # # This file is part of Fintic project, developed by Neythen Treloar and Justin Dunn # # stockTicker can not be copied and/or distributed without the express # permission of Fintic import sys, select import os import threading from PIL import Image, ImageDraw, ImageFont, ImageSequence Image.init() import time import csv import requests import pexpect from rgbmatrix import RGBMatrix, RGBMatrixOptions from rgbmatrix.graphics import * from multiprocessing import Process import traceback import json from datetime import datetime import matplotlib.colors as mcolors def getInput(Block=False): if Block or select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): msg = sys.stdin.read(1) #sys.stdin.flush() else: msg = '' return msg class StockTicker(): def __init__(self): #Define global resources self.symbols = [] self.delay = 0.02 self.greenORred = (255, 255, 255) #self.blank = Image.open('logos/blank.png') self.blank = Image.new('RGB', (10, 32)) self.running = True settings = json.load(open('csv/general_settings.json', 'r')) self.brightness = settings['brightness']*10 # Configuration for the matrix options = RGBMatrixOptions() options.rows = 32 options.cols = 64 options.chain_length = 2 options.parallel = 1 options.hardware_mapping = 'adafruit-hat' # If you have an Adafruit HAT: 'adafruit-hat' options.gpio_slowdown = 2 options.brightness = self.brightness self.matrix = RGBMatrix(options = options) #sys.exit() self.points = True # display crypto change in points or percent self.functions = {'Stocks': self.getStockImage, 'Crypto': self.getCryptoImage, 'Forex': self.getForexImage, 'Daily Forecast':self.getDailyWeatherImage, 'Current Weather': self.getTodayWeatherImage, 'Sports (Team Stats)':lambda : self.getLeagueTableImage('premier_league'), 'Sports (Past Games)': lambda:self.getLeagueImage('NBA', 'past'), 'Sports (Upcoming Games)': lambda : self.getLeagueImage('NHL', 'future'), 'Sports (Live Games)': lambda: self.getLeagueImage('NBA', 'live'), 'News':self.getNewsImage, 'Custom Messages': self.getUserMessages, 'Commodities': self.getCommoditiesImage, 'Indices': self.getIndicesImage, 'Movies': self.getMoviesImage, 'Stocks Prof': self.getStockProfessional, 'Crypto Prof': self.getCryptoProfessional, 'Forex Prof': self.getForexProfessional, 'Current Weather Prof': self.getTodayWeatherProfessional, 'News Prof':self.getNewsProfessional, 'Commodities Prof':self.getCommoditiesProfessional, 'Indices Prof': self.getIndicesProfessional, 'Daily Forecast Prof':self.getDailyWeatherProfessional, 'Sports (Team Stats) Prof':lambda : self.getLeagueTableProfessional('NHL'), 'Sports (Upcoming Games) Prof': lambda : self.getLeagueProfessional('NHL', 'future'), 'Sports (Past Games) Prof': lambda : self.getLeagueProfessional('NBA', 'past'), 'Custom Messages Prof': self.getUserMessagesProfessional, 'Custom Images Prof': self.getUserImagesProfessional, 'Movies Prof': self.getMoviesProfessional} self.JSONs = {'Stocks': 'csv/stocks_settings.json', 'Crypto': 'csv/crypto_settings.json', 'Forex': 'csv/forex_settings.json', 'Daily Forecast':'csv/daily_weather.json', 'Current Weather': 'csv/current_weather.json', 'Commodities':'csv/commodities_settings.json', 'Indices': 'csv/indices_settings.json', 'Sports (Team Stats)': 'csv/league_tables.json', 'Sports (Past Games)': 'csv/past_games.json', 'Sports (Upcoming Games)': 'csv/upcoming_games.json', 'Sports (Live Games)': 'csv/live_games.json', 'Movies': 'csv/movie_settings.json', 'News':'csv/news_settings.json', 'Custom Images': 'csv/image_settings.json', 'Custom GIFs': 'csv/GIF_settings.json', 'Custom Messages': 'csv/message_settings.json', 'Stocks Prof': 'csv/stocks_settings.json', 'Crypto Prof': 'csv/crypto_settings.json', 'Forex Prof': 'csv/forex_settings.json', 'Current Weather Prof': 'csv/current_weather.json', 'News Prof':'csv/news_settings.json', 'Commodities Prof':'csv/commodities_settings.json', 'Indices Prof': 'csv/indices_settings.json', 'Daily Forecast Prof':'csv/daily_weather.json', 'Sports (Team Stats) Prof': 'csv/league_tables.json', 'Sports (Upcoming Games) Prof': 'csv/upcoming_games.json', 'Sports (Past Games) Prof': 'csv/past_games.json', 'Custom Messages Prof': 'csv/message_settings.json', 'Custom Images Prof': 'csv/image_settings.json', 'Movies Prof': 'csv/movie_settings.json'} def openImage(self, image_file): image = Image.open(image_file) image = image.convert('RGB') # Make image fit our screen. #image.thumbnail((self.matrix.width, self.matrix.height), Image.ANTIALIAS) #image = image.convert('RGB') return image def degreesToCompass(self, deg): dirs = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'] return dirs[int((deg+22.5)//45)%8] def setImage(self, image, offset_x = 0, offset_y = 0, unsafe=True, min_x = 0, max_x = 128, min_y = 0, max_y = 32): if (image.mode != "RGB"): image = image.convert('RGB') if unsafe: #In unsafe mode we directly acceshow to send commands to running python processs the underlying PIL image array #in cython, which is considered unsafe pointer accecss, #however it's super fast and seems to work fine #https://groups.google.com/forum/#!topic/cython-users/Dc1ft5W6KM4 img_width, img_height = image.size self.matrix.SetPixelsPillow(offset_x, offset_y, img_width, img_height, image) else: # First implementation of a SetImage(). OPTIMIZE_ME: A more native # implementation that directly reads the buffer and calls the underlying # C functions can certainly be faster. img_width, img_height = image.size pixels = image.load() for y in range(max(0, -offset_y), min(img_height, self.matrix.height - offset_y)): for x in range(max(0, -offset_x), min(img_width, self.matrix.width - offset_x)): if min_x <= x + offset_x <= max_x and min_y <= y + offset_y <= max_y: (r, g, b) = pixels[x, y] self.matrix.SetPixel(x + offset_x, y + offset_y, r*self.brightness, g*self.brightness, b*self.brightness) def scrollImage(self, image, offset_x = 0, offset_y = 0, frame_skip = 10, gif = False, pause_frames = 0): img_width, img_height = image.size kill = False while offset_x > -(img_width+1): if offset_x == 0: while pause_frames > 0: if pause_frames%frame_skip == 0: self.incrementGIF(image) pause_frames -=1 if gif: self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y) else: self.double_buffer.SetImage(image, offset_x, offset_y) for y in range(self.matrix.height): self.matrix.SetPixel(offset_x + img_width +1 , y , 0,0,0) self.matrix.SetPixel(offset_x + img_width , y , 0,0,0) self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer) time.sleep(self.delay) kill = self.checkKilled() if kill: break if kill: break # for animation in gifs if offset_x%frame_skip == 0: self.incrementGIF(image) #image = image.convert('RGB') offset_x -= 1 #self.setImage(image.convert('RGB'), offset_x = offset_x, offset_y = offset_y) if gif: self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y) else: self.double_buffer.SetImage(image, offset_x, offset_y) buff = 0 # remove the ppixels behind the image, to stop trailing self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer) for y in range(self.matrix.height): self.matrix.SetPixel(offset_x + img_width +1 , y , 0,0,0) self.matrix.SetPixel(offset_x + img_width , y , 0,0,0) time.sleep(self.delay) kill = self.checkKilled() if kill: break return kill def scrollImageY(self, image, direction = 1, offset_x = 0, offset_y = 0, frame_skip = 10, gif = False): kill = False while offset_y != 0: # for animation in gifs if offset_y%frame_skip == 0: self.incrementGIF(image) offset_y += direction if gif: self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y) else: self.double_buffer.SetImage(image, offset_x, offset_y) self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer) time.sleep(self.delay) kill = self.checkKilled() if kill: break return kill def scrollImageTransition(self, image_files, offset_x = 0, offset_y = 0, stocks = True): # use two image files and switch between them with a seemless transition current_img = 1 image1 = self.openImage(image_files[0]).convert('RGB') image2 = self.openImage(image_files[1]).convert('RGB') double_buffer = self.matrix.CreateFrameCanvas() kill = False while True: if current_img == 1: if stocks: update_process = Process(target = self.getFullStockImage, args = (1,)) update_process.start() image1 = self.openImage(image_files[0]).convert('RGB') image2 = self.openImage(image_files[1]).convert('RGB') elif current_img == 2: if stocks: update_process = Process(target = self.getFullStockImage, args = (2,)) update_process.start() image1 = self.openImage(image_files[1]).convert('RGB') image2 = self.openImage(image_files[0]).convert('RGB') img_width, img_height = image1.size while offset_x > -img_width: offset_x -= 1 double_buffer.SetImage(image1, offset_x, offset_y) if offset_x + img_width < self.matrix.width: # if the image is ending double_buffer.SetImage(image2, offset_x, offset_y) double_buffer = self.matrix.SwapOnVSync(double_buffer) time.sleep(self.delay) kill = self.checkKilled() if kill: break if stocks: image1.close() image2.close() if kill: break if stocks: update_process.join() update_process.terminate() if current_img == 1: current_img = 2 elif current_img == 2: current_img = 1 offset_x = 0 update_process.join() update_process.terminate() def scrollImageStacked(self, image, offset_x = 0, offset_y = 0): img_width, img_height = image.size while offset_x > -img_width - 128: offset_x -= 1 self.setImage(image, offset_x = offset_x+128, offset_y = offset_y) self.setImage(image, offset_x = offset_x, offset_y = offset_y+20) kill = self.checkKilled() time.sleep(self.delay) return kill def updateMultiple(self, options): for option in options: if option not in ['Custom GIFs', 'Custom Images', 'Custom Messages']: # these images are already saved in user uploads, dodnt need to update them img = self.functions[option]() img.save('./display_images/'+ option+ '.ppm') def incrementGIF(self, image): try: image.seek(self.frame) except EOFError: self.frame = 0 image.seek(self.frame) self.frame +=1 def checkKilled(self): kill = False try: msg = getInput() if msg == 'K': self.resetMatrix() kill = True self.process_msg(msg) except KeyboardInterrupt: sys.stdout.flush() pass return kill def set_delay(self,speed): if speed.lower() == 'slow': self.delay = 0.03 elif speed.lower() == 'medium': self.delay = 0.02 elif speed.lower() == 'fast': self.delay = 0.01 return self.delay def scrollFunctionsAnimated(self, options, animation = 'down', repeat = True): # scrolls trhough all functions with animation. Updates functions and remakes images when each function not being dispplayed self.updateMultiple([options[0]]) kill = False i = 0 # keep track of which image we are displaying self.double_buffer = self.matrix.CreateFrameCanvas() while True: update_process = Process(target = self.updateMultiple, args = ([options[(i+1) % len(options)]],)) update_process.start() f = open(self.JSONs[options[(i) % len(options)]]) settings = json.load(f) f.close() self.set_delay(settings['speed']) animation = settings['animation'].lower() if options[i % len(options)] == 'Custom Images': images = self.getUserImages() elif options[i % len(options)] == 'Custom GIFs': images = self.getUserGIFs() elif options[i % len(options)] == 'Custom Messages': images = self.getUserMessages() else: #these options just have a single ppm image image = self.openImage('./display_images/' + options[i % len(options)] +'.ppm') images = [image] for image in images: img_width, img_height = image.size offset_x = 0 if animation == 'continuous': offset_x = 128 elif animation in ['up', 'down']: offset_x = max(0, 128-img_width) offset_y = 0 #first scroll image in from bottom frame_skip = int((1/15)/self.delay) #controls how fast gifs run self.frame = 0 pause_frames = int(0.5/self.delay) if animation == 'up': offset_y = 33 direction = -1 kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs') elif animation == 'down': direction = 1 offset_y = -33 kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs') if kill: break offset_y = 0 if animation in ['up', 'down']: while pause_frames > 0: if pause_frames%frame_skip == 0: self.incrementGIF(image) pause_frames -=1 if options[i % len(options)] != 'Custom GIFs': self.double_buffer.SetImage(image, offset_x, offset_y) else: self.double_buffer.SetImage(image.convert('RGB'), offset_x, offset_y) self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer) time.sleep(self.delay) kill = self.checkKilled() if kill: break if kill: break if kill: break try: pause = float(settings['pause']) except: pause = 0 pause_frames = int(float(pause)/self.delay) kill = self.scrollImage(image, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = options[i % len(options)] == 'Custom GIFs', pause_frames = pause_frames) if kill: break if kill:break if not repeat: break update_process.join() update_process.terminate() i+=1 def scrollProfessionalAnimated(self, options, animation = 'on'): # scrolls trhough all functions with animation. Updates functions and remakes images when each function not being dispplayed top = options[0] bottom = options[1] self.updateMultiple([top[0], bottom[0]]) kill = False i1 = 0 # keep track of which image we are displaying i2 = 0 # keep track of which image we are displaying self.double_buffer = self.matrix.CreateFrameCanvas() update_process = Process(target = self.updateMultiple, args = ([top[(i1+1) % len(top)]+ ' Prof', bottom[(i2+1) % len(bottom)]+ ' Prof' ],)) update_process.start() self.updateMultiple([top[i1 % len(top)]+ ' Prof', bottom[i2 % len(bottom)]+ ' Prof' ]) image1 = self.openImage('./display_images/' + top[i1 % len(top)] +' Prof.ppm') image1 = image1.convert('RGB') image2 = self.openImage('./display_images/' + bottom[i2 % len(bottom)] +' Prof.ppm') image2 = image2.convert('RGB') settings1 = json.load(open(self.JSONs[top[i1 % len(top)]])) delay_t1 = self.set_delay(settings1['speed']) animation1 = settings1['animation'].lower() settings2 = json.load(open(self.JSONs[bottom[i2 % len(bottom)] ])) try: delay_t2 = self.set_delay(settings2['speed2']) except: delay_t2 = self.set_delay(settings2['speed']) animation2 = settings2['animation'].lower() if animation1 == 'continuous': offset_y1 = 0 offset_x1 = 128 else: offset_y1 = -16 offset_x1 = 0 if animation2 == 'continuous': offset_y2 = 16 offset_x2 = 128 else: offset_y2 = 32 offset_x2 = 0 frame_skip = int((1/15)/self.delay) #controls how fast gifs run self.frame = 0 img_width1, img_height1 = image1.size img_width2, img_height2 = image2.size kill = False update_t1 = time.time() update_t2 = time.time() while True: if offset_x1 < -(img_width1+1): i1 += 1 settings1 = json.load(open(self.JSONs[top[i1 % len(top)]])) delay_t1 = self.set_delay(settings1['speed']) animation1 = settings1['animation'].lower() if animation1 == 'continuous': offset_y1 = 0 offset_x1 = 128 else: offset_y1 = -16 offset_x1 = 0 update_process.join() update_process.terminate() update_process = Process(target = self.updateMultiple, args = ([top[(i1+1) % len(top)]+ ' Prof'],)) update_process.start() image1 = self.openImage('./display_images/' + top[i1 % len(top)] +' Prof.ppm') image1 = image1.convert('RGB') img_width1, img_height1 = image1.size if offset_x2 < -(img_width2+1): i2 += 1 settings2 = json.load(open(self.JSONs[bottom[(i2) % len(bottom)]])) try: delay_t2 = self.set_delay(settings2['speed2']) except: delay_t2 = self.set_delay(settings2['speed']) animation2 = settings2['animation'].lower() if animation2 == 'continuous': offset_y2 = 16 offset_x2 = 128 else: offset_y2 = 32 offset_x2 = 0 update_process.join() update_process.terminate() update_process = Process(target = self.updateMultiple, args = ([bottom[i2 % len(bottom)]+ ' Prof'],)) update_process.start() image2 = self.openImage('./display_images/' + bottom[i2 % len(bottom)] +' Prof.ppm') image2 = image2.convert('RGB') img_width2, img_height2 = image2.size if time.time() - update_t1 > delay_t1: update_t1 = time.time() if offset_y1 < 0: offset_y1+=1 else: offset_x1 -= 1 if time.time() - update_t2 > delay_t2: update_t2 = time.time() if offset_y2 > 16: offset_y2-=1 else: offset_x2 -= 1 if kill: break #image = image.convert('RGB') self.double_buffer.SetImage(image1, offset_x1, offset_y1) self.double_buffer.SetImage(image2, offset_x2, offset_y2) buff = 0 # remove the ppixels behind the image, to stop trailing self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer) for y in range(16): self.matrix.SetPixel(offset_x1 + img_width1 +1 , y , 0,0,0) self.matrix.SetPixel(offset_x1 + img_width1 , y , 0,0,0) for y in range(16,32): self.matrix.SetPixel(offset_x2 + img_width2 +1 , y , 0,0,0) self.matrix.SetPixel(offset_x2 + img_width2 , y , 0,0,0) kill = self.checkKilled() if kill: break if kill: break def scrollMultiple(self, animation = 'down'): # scrolls trhough all functions with animation. Updates functions and remakes images when each function not being dispplayed # read lines from csv images = [] delays = [] kinds = [] f = open('csv/multiple.csv', 'r') CSV = csv.reader(f) next(CSV) font = ImageFont.load("./fonts/texgyre-27.pil") for row in CSV: kind, content, delay = row delays.append(delay) kinds.append(kind) if kind == 'text': images.append(self.textImage(content, font, 255, 255, 0, True, w_buff = 50)) elif kind == 'image': images.append(self.openImage(content).convert('RGB')) elif kind == 'gif': images.append(self.openImage(content)) f.close() kill = False i = 0 # keep track of which image we are displaying self.double_buffer = self.matrix.CreateFrameCanvas() while True: image = images[i%len(images)] delay = delays[i%len(images)] kind = kinds[i%len(images)] img_width, img_height = image.size offset_x = 0 if animation == 'traditional': offset_x = 128 elif animation == 'continuous': offset_x = 0 elif animation in ['up', 'down']: offset_x = max(0, 128-img_width) offset_y = 0 #first scroll image in from bottom frame_skip = int((1/15)/self.delay) #controls how fast gifs run self.frame = 0 pause_frames = int(float(delay)/self.delay) if animation == 'up': offset_y = 33 direction = -1 kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = kind=='gif') elif animation == 'down': direction = 1 offset_y = -33 kill = self.scrollImageY(image, direction = direction, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = kind=='gif') offset_y = 0 if kill: break kill = self.scrollImage(image, offset_x = offset_x, offset_y = offset_y, frame_skip = frame_skip, gif = kind=='gif', pause_frames = pause_frames) if kill: break i+=1 def textImage(self, text, font, r = 255, g = 255, b = 255, matrix_height = False, w_buff = 3, h_buff = 3, background = False, location = False): #creates and returns a ppm image containing the text in the supplied font and colour width, height = self.get_text_dimensions(text, font) if matrix_height: height = 32 img = Image.new('RGB', (width + w_buff, height + h_buff)) d = ImageDraw.Draw(img) if background: br, bg, bb = background d.rectangle(xy = (0, 0, width + w_buff, height + h_buff), fill = (br, bg, bb)) #outline = (255, 255, 255), #width = 0) #use outline and width to add a border if location: d.text(location, text, fill=(r, g, b), font=font) else: d.text((0, 0), text, fill=(r, g, b), font=font) return img def getUserMessages(self): #displays the text entered in the webpage by the user. f = open('csv/message_settings.json', 'r') all_settings = json.load(f) f.close() colours = {'Black':(0,0,0), 'White':(255,255,255), 'Red':(255,0,0), 'Green':(0,255,0), 'Blue':(0,0,255), 'Purple':(255,0,255), 'Yellow':(255,255,0), 'Cyan':(0,255,255)} imgs = [] for ind, message in enumerate(all_settings['messages']): font = ImageFont.load("./fonts/10x20.pil") location = (0, 4) if message["size"] == 'Large': font = ImageFont.load("./fonts/texgyre-27.pil") location = (0, -2) elif message["size"] == 'Small': font = ImageFont.load("./fonts/6x13.pil") location = (0, 7) r,g,b = colours[message['text_colour']] background = colours[message['background_colour']] img = self.textImage(message['text'], font, int(r), int(g), int(b), True, w_buff = 5, background = background, location = location) if all_settings['title'] and ind == 0: title_img = self.openImage('feature_titles/message.png') imgs.append(self.stitchImage([title_img, img])) else: imgs.append(img) return imgs def getUserMessagesProfessional(self): f = open('csv/message_settings.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/message.png') image_list = [title_img] else: image_list = [] colours = {'Black':(0,0,0), 'White':(255,255,255), 'Red':(255,0,0), 'Green':(0,255,0), 'Dark Green':(0,100,0), 'Blue':(0,0,255), 'Purple':(145,0,255), 'Pink':(255,0,255), 'Yellow':(255,255,0), 'Orange':(255,130,0), 'Gold':(255,190,0), 'Gray':(100,100,100), 'Cyan':(0,255,255)} blank = Image.new('RGB', (0, 16)) for i, message in enumerate(all_settings['messages']): if (i == len(all_settings['messages'])-1): font = ImageFont.load("./fonts/6x13.pil") location = (5, 2) r,g,b = colours[message['text_colour']] background = colours[message['background_colour']] msg_img = self.textImage(message['text'], font, int(r), int(g), int(b), True, w_buff = 11, background = background, location = location) img = Image.new('RGB', (msg_img.size[0] + 5, 32)) img.paste(msg_img, (0,0)) image_list.append(img) image_list.append(blank) else: font = ImageFont.load("./fonts/6x13.pil") location = (5, 2) r,g,b = colours[message['text_colour']] background = colours[message['background_colour']] msg_img = self.textImage(message['text'], font, int(r), int(g), int(b), True, w_buff = 11, background = background, location = location) img = Image.new('RGB', (msg_img.size[0] + 130, 32)) img.paste(msg_img, (0,0)) image_list.append(img) image_list.append(blank) return self.stitchImage(image_list) def displayGIF(self, gif, delay = 0.5, repeat = True): # To iterate through the entire gif i = 0 while True: try: gif.seek(i) except EOFError: if not repeat: break i = 0 gif.seek(i) # do something to im self.setImage(gif.convert('RGB')) time.sleep(delay) i += 1 try: msg = getInput() if msg == 'K': gif.close() self.resetMatrix() break self.process_msg(msg) except KeyboardInterrupt: sys.stdout.flush() pass def scrollGIF(self, gif, offset_x = 0, offset_y = 0): # To iterate through the entire gif i = 0 img_width, img_height = gif.size while offset_x > -img_width: offset_x -= 1 try: gif.seek(i) except EOFError: i = 0 gif.seek(i) # do something to im self.setImage(gif.convert('RGB'), offset_x = offset_x) time.sleep(self.delay) if offset_x % 20 == 0: i += 1 for x in range(offset_x + img_width, 128): for y in range(self.matrix.height): self.matrix.SetPixel(x , y , 0,0,0) kill = self.checkKilled() if kill: break return kill #Using change between min and day price give appropriate arrow #and set the overall change colour def getArrow(self, CHANGE, professional = False): self.greenORred logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'stocks') if(CHANGE>0): Arrow = Image.open(os.path.join(logos_path, 'up-1.png')) self.greenORred = (0, 255, 0) else: Arrow = Image.open(os.path.join(logos_path, 'down-1.png')) self.greenORred = (255, 0, 0) CHANGE = (CHANGE * -1) if professional: w, h = Arrow.size Arrow = Arrow.resize((int(w/2), int(h/2))) return Arrow, CHANGE def get_text_dimensions(self, text_string, font): canvas = Image.new('RGB', (10000,100)) draw = ImageDraw.Draw(canvas) monospace = font text = text_string white = (255,255,255) draw.text((0, 0), text, font=monospace, fill=white) bbox = canvas.getbbox() width = bbox[2]-bbox[0] height = bbox[3]-bbox[1] return width,height #Draw Ticker, current and change onto one image def textToImage(self, TICKER, CURRENT, ARROW, percent_change = False, point_change = False, font = ImageFont.load("./fonts/10x20.pil")): w1, text_height = self.get_text_dimensions(TICKER, font) w2, text_height = self.get_text_dimensions(CURRENT, font) text_width_current = max(w1,w2) img = Image.new('RGB', (text_width_current +1000 , 32)) d = ImageDraw.Draw(img) d.text((4, 0), TICKER, fill=(255, 255, 255), font=font) d.text((4, 16), CURRENT, fill=self.greenORred, font=font) if percent_change: d.text(((w1+7), 14 - text_height), percent_change, fill=self.greenORred, font=font) w, h = self.get_text_dimensions(percent_change, font) w1 += 7 + w if point_change: img.paste(ARROW, ((w2+ 9),18)) d.text(((w2+29), 16), point_change, fill=self.greenORred, font=font) w,h = self.get_text_dimensions(point_change, font) w2 += 29 + w img = img.crop((0,0,max(w1, w2) + 20,32)) return img def textToImageProf(self, TICKER, CURRENT, CHANGE, ARROW, font): text_width_current, text_height = self.get_text_dimensions(CURRENT, font) img = Image.new('RGB', (text_width_current +100 , 32)) d = ImageDraw.Draw(img) d.text((4, 0), TICKER, fill=(255, 255, 255), font=font) d.text((4, 8), CURRENT, fill=self.greenORred, font=font) img.paste(ARROW, ((text_width_current + 7),10)) d.text(((text_width_current+18), 8), CHANGE, fill=self.greenORred, font=font) text_width_change, text_height = self.get_text_dimensions(CHANGE, font) newWidth = text_width_current + text_width_change +30 img = img.crop((0,0,newWidth,32)) return img #Stitch the logo & prices picture into one image def stitchImage(self, image_list): widths, heights = zip(*(i.size for i in image_list)) total_width = sum(widths) max_height = max(heights) new_im = Image.new('RGB', (total_width, max_height)) x_offset = 0 for im in image_list: new_im.paste(im, (x_offset,0)) x_offset += im.size[0] return new_im def resetMatrix(self): for x in range(self.matrix.width): for y in range(self.matrix.height): self.matrix.SetPixel(x , y , 0,0,0) def getCryptoImage(self): f = open('csv/crypto_settings.json', 'r') all_crypto_settings = json.load(f) f.close() if all_crypto_settings['title']: title_img = self.openImage('feature_titles/crypto.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] coin_info = all_crypto_settings['symbols'] coin_bases = list(coin_info.keys()) for i, cb in enumerate(coin_bases): try: ticker, base = cb.split(',') current = float(coin_info[cb]["current"]) point_change = float(coin_info[cb]["24hr_change"]) point_change2 = abs(point_change) point_changefinal = '{0:.10f}'.format(point_change2).rstrip("0") current_final = '{0:.10f}'.format(current).rstrip("0") percent_change = float(coin_info[cb]["percent_change"]) arrow, change = self.getArrow(point_change) percent_change = '%.2f' % abs(percent_change) + '%' point_change = str(point_changefinal) current = str(current_final) if not all_crypto_settings['percent']: percent_change = False if not all_crypto_settings['point']: point_change = False midFrame = self.textToImage(ticker + '(' + base + ')', current, arrow, percent_change, point_change) #IMAGE THE TEXT if all_crypto_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'crypto') logo = self.openImage(os.path.join(logos_path, ticker + '.png')) stitchedStock = self.stitchImage([logo,midFrame]) except Exception as e: stitchedStock = midFrame else: stitchedStock = midFrame image_list.append(stitchedStock) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) return finalDisplayImage def getCryptoProfessional(self): self.blank = Image.new('RGB', (0, 16)) f = open('csv/crypto_settings.json', 'r') all_crypto_settings = json.load(f) f.close() if all_crypto_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/crypto.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] coin_info = all_crypto_settings['symbols'] coin_bases = list(coin_info.keys()) for i, cb in enumerate(coin_bases): try: ticker, base = cb.split(',') current = float(coin_info[cb]["current"]) current_final = '{0:.10f}'.format(current).rstrip("0") change = float(coin_info[cb]["24hr_change"]) change2 = abs(change) changefinal = '{0:.10f}'.format(change2).rstrip("0") arrow, change = self.getArrow(change, professional=True) if all_crypto_settings["percent"]: # convert percent to points change = '%.2f' % abs(float(coin_info[cb]['percent_change'])) + '%' else: change = str(changefinal) current = str(current_final) midFrame = self.textToImageProf(ticker + '(' + base + ')', current, change, arrow, font=ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT if all_crypto_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'crypto') logo = self.openImage(os.path.join(logos_path, ticker + '.png')) w,h = logo.size logo=logo.resize((int(w/2), int(h/2))) stitchedStock = self.stitchImage([logo,midFrame]) except: stitchedStock = midFrame else: stitchedStock = midFrame image_list.append(stitchedStock) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) self.blank = Image.new('RGB', (10, 32)) return finalDisplayImage def getIndicesImage(self): f = open('csv/indices_settings.json', 'r') all_indices_settings = json.load(f) f.close() if all_indices_settings['title']: title_img = self.openImage('feature_titles/indices.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] index_info = all_indices_settings['symbols'] symbols = list(index_info.keys()) for i, symbol in enumerate(symbols): try: info = index_info[symbol] change = float(info['point_change']) #TEXT symb = symbol ticker = info['name'] #TEXT arrow, change = self.getArrow(change) point_change = '%.2f' % abs(change) percent_change = '%.2f' % abs(float(info['percent_change'])) + '%' # point_change2 = abs(change) # point_changefinal = '{0:.10f}'.format(point_change2).rstrip("0") # point_change = str(point_changefinal) current = '%.2f' % float(info['current']) # current_final = '{0:.10f}'.format(current).rstrip("0") # current = str(current_final) if not all_indices_settings['percent']: percent_change = False if not all_indices_settings['point']: point_change = False midFrame = self.textToImage(ticker, current, arrow, percent_change, point_change) #IMAGE THE TEXT if all_indices_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'indices') logo = self.openImage(os.path.join(logos_path, symb + '.png')) stitchedIndex = self.stitchImage([logo,midFrame]) except Exception as e: stitchedIndex = midFrame else: stitchedIndex = midFrame image_list.append(stitchedIndex) image_list.append(self.blank) except Exception as e: pass finalDisplayImage = self.stitchImage(image_list) return finalDisplayImage def getIndicesProfessional(self): self.blank = Image.new('RGB', (0, 16)) f = open('csv/indices_settings.json', 'r') all_indices_settings = json.load(f) f.close() if all_indices_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/indices.png') image_list = [title_img, Image.new('RGB', (5, 16))] image_list.append(self.blank) else: image_list = [] index_info = all_indices_settings['symbols'] symbols = list(index_info.keys()) for i, symbol in enumerate(symbols): try: info = index_info[symbol] change = float(info['point_change']) #TEXT symb = symbol ticker = info['name'] #TEXT arrow, change = self.getArrow(change, professional=True) if all_indices_settings["percent"]: change = '%.2f' % abs(float(info['percent_change'])) + '%' else: change = '%.2f' % abs(change) current = '%.2f' % float(info['current']) midFrame = self.textToImageProf(ticker, current, change, arrow, font=ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT if all_indices_settings['logos']: try: try: #load the tiny logo logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'tiny_indices') logo = Image.open(os.path.join(logos_path, ticker + '.png')) except: # load the big logo and scale it logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'indices') logo = Image.open(os.path.join(logos_path, symb + '.png')) # half the size of the logo width, height = logo.size logo = logo.resize((int(width/2), int(height/2))) stitchedIndex = self.stitchImage([logo,midFrame]) except Exception as e: stitchedIndex = midFrame else: stitchedIndex = midFrame image_list.append(stitchedIndex) image_list.append(self.blank) except Exception as e: pass finalDisplayImage = self.stitchImage(image_list) self.blank = Image.new('RGB', (10, 32)) return finalDisplayImage def getCommoditiesImage(self): f = open('csv/commodities_settings.json', 'r') all_commodities_settings = json.load(f) f.close() if all_commodities_settings['title']: title_img = self.openImage('feature_titles/commodities.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] commodity_info = all_commodities_settings['symbols'] symbols = list(commodity_info.keys()) for i, symbol in enumerate(symbols): try: info = commodity_info[symbol] change = float(info['24hr_change']) #TEXT ticker = symbol #TEXT unit = info['unit'] ticker = symbol + '(' + unit + ')' #TEXT arrow, change = self.getArrow(change) percent_change = '%.2f' % abs(float(info['percent_change'])) + '%' point_change2 = abs(change) point_changefinal = '{0:.10f}'.format(point_change2).rstrip("0") point_change = str(point_changefinal) current = float(info["current"]) current_final = '{0:.10f}'.format(current).rstrip("0") current = str(current_final) if not all_commodities_settings['percent']: percent_change = False if not all_commodities_settings['point']: point_change = False midFrame = self.textToImage(ticker, current, arrow, percent_change, point_change) #IMAGE THE TEXT if all_commodities_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'commodities') logo = self.openImage(os.path.join(logos_path, ticker + '.png')) stitchedCommodity = self.stitchImage([logo,midFrame]) except Exception as e: stitchedCommodity = midFrame else: stitchedCommodity = midFrame image_list.append(stitchedCommodity) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) return finalDisplayImage def getCommoditiesProfessional(self): self.blank = Image.new('RGB', (0, 16)) f = open('csv/commodities_settings.json', 'r') all_commodities_settings = json.load(f) f.close() if all_commodities_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/commodities.png') image_list = [title_img, Image.new('RGB', (5, 16))] image_list.append(self.blank) else: image_list = [] commodity_info = all_commodities_settings['symbols'] symbols = list(commodity_info.keys()) for i, symbol in enumerate(symbols): try: info = commodity_info[symbol] change = float(info['24hr_change']) #TEXT unit = info['unit'] ticker = symbol + '(' + unit + ')' #TEXT arrow, change = self.getArrow(change, professional=True) if all_commodities_settings["percent"]: change = '%.2f' % abs(float(info['percent_change'])) + '%' else: point_change2 = abs(change) point_changefinal = '{0:.10f}'.format(point_change2).rstrip("0") change = str(point_changefinal) current = float(info["current"]) current_final = '{0:.10f}'.format(current).rstrip("0") current = str(current_final) midFrame = self.textToImageProf(ticker, current, change, arrow, font=ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT if all_commodities_settings['logos']: try: try: #load the tiny logo logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'tiny_commodities') logo = Image.open(os.path.join(logos_path, ticker + '.png')) except: # load the big logo and scale it logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'commodities') logo = Image.open(os.path.join(logos_path, ticker + '.png')) # half the size of the logo width, height = logo.size logo = logo.resize((int(width/2), int(height/2))) stitchedCommodity = self.stitchImage([logo,midFrame]) except Exception as e: stitchedCommodity = midFrame else: stitchedCommodity = midFrame image_list.append(stitchedCommodity) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) self.blank = Image.new('RGB', (10, 32)) return finalDisplayImage def getForexImage(self): f = open('csv/forex_settings.json', 'r') all_forex_settings = json.load(f) f.close() if all_forex_settings['title']: title_img = self.openImage('feature_titles/forex.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] forex_settings = all_forex_settings['symbols'] symbol_bases = list(forex_settings.keys()) for i, sb in enumerate(symbol_bases): try: symbol, base = sb.split(',') current = float(forex_settings[sb]['current']) current_final = '{0:.10f}'.format(current).rstrip("0") change = float(forex_settings[sb]['24hr_change']) change2 = abs(change) changefinal = '{0:.10f}'.format(change2).rstrip("0") percent_change = '%.2f' % abs(float(forex_settings[sb]['percent_change'])) +'%' point_change = str(changefinal) if not all_forex_settings['percent']: percent_change = False if not all_forex_settings['point']: point_change = False arrow, change = self.getArrow(change) current = str(current_final) midFrame = self.textToImage(symbol+ '(' + base + ')', current, arrow, percent_change, point_change) #IMAGE THE TEXT if all_forex_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'currencies') logo = Image.open(os.path.join(logos_path, symbol.upper() + '.png')) bse = Image.open(os.path.join(logos_path, base.upper() + '.png')) new_im = Image.new('RGB', (32, 32)) new_im.paste(bse, (0,10), bse.convert('RGBA')) new_im.paste(logo, (10,0), logo.convert('RGBA')) stitchedStock = self.stitchImage([new_im, midFrame]) image_list.append(new_im) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() image_list.append(midFrame) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) return finalDisplayImage def getForexProfessional(self): self.blank = Image.new('RGB', (0, 16)) f = open('csv/forex_settings.json', 'r') all_forex_settings = json.load(f) f.close() if all_forex_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/forex.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] forex_settings = all_forex_settings['symbols'] symbol_bases = list(forex_settings.keys()) for i, sb in enumerate(symbol_bases): try: symbol, base = sb.split(',') current = float(forex_settings[sb]['current']) current_final = '{0:.10f}'.format(current).rstrip("0") change = float(forex_settings[sb]['24hr_change']) change2 = abs(change) changefinal = '{0:.10f}'.format(change2).rstrip("0") arrow, change = self.getArrow(change, professional = True) if all_forex_settings["percent"]: change = abs(float(forex_settings[sb]['percent_change'])) change = '%.2f' % change + '%' else: change = str(changefinal) current = str(current_final) midFrame = self.textToImageProf(symbol + '(' + base + ')', current, change, arrow, font = ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT if all_forex_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'currencies') logo = Image.open(os.path.join(logos_path, symbol.upper() + '.png')) bse = Image.open(os.path.join(logos_path, base.upper() + '.png')) new_im = Image.new('RGB', (32, 32)) new_im.paste(bse, (0,10), bse.convert('RGBA')) new_im.paste(logo, (10,0), logo.convert('RGBA')) width, height = new_im.size new_im = new_im.resize((int(width/2), int(height/2))) stitchedStock = self.stitchImage([new_im, midFrame]) image_list.append(new_im) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() image_list.append(midFrame) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) self.blank = Image.new('RGB', (10, 32)) return finalDisplayImage def getStockImage(self): f = open('csv/stocks_settings.json', 'r') all_stocks_settings = json.load(f) f.close() if all_stocks_settings['title']: title_img = self.openImage('feature_titles/stocks.png') image_list = [title_img] image_list.append(self.blank) else: image_list = [] stock_info = all_stocks_settings['symbols'] symbols = list(stock_info.keys()) for i, symbol in enumerate(symbols): try: info = stock_info[symbol] change = float(info['change']) #TEXT ticker = symbol #TEXT arrow, change = self.getArrow(change) percent_change = '%.2f' % abs(float(info['percent_change'])) + '%' point_change = '%.2f' % abs(change) current = '%.2f' % float(info['current']) #TEXT if not all_stocks_settings['percent']: percent_change = False if not all_stocks_settings['point']: point_change = False midFrame = self.textToImage(ticker, current, arrow, percent_change, point_change) #IMAGE THE TEXT if all_stocks_settings['logos']: try: logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'stocks') logo = self.openImage(os.path.join(logos_path, ticker + '.png')) stitchedStock = self.stitchImage([logo,midFrame]) except Exception as e: stitchedStock = midFrame else: stitchedStock = midFrame image_list.append(stitchedStock) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) return finalDisplayImage def getStockProfessional(self): self.blank = Image.new('RGB', (0, 16)) f = open('csv/stocks_settings.json', 'r') all_stocks_settings = json.load(f) f.close() if all_stocks_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/stocks.png') image_list = [title_img, Image.new('RGB', (5, 16))] image_list.append(self.blank) else: image_list = [] stock_info = all_stocks_settings['symbols'] symbols = list(stock_info.keys()) for i, symbol in enumerate(symbols): try: info = stock_info[symbol] change = float(info['change'])#TEXT ticker = symbol #TEXT arrow, change = self.getArrow(change, professional=True) if all_stocks_settings["percent"]: change = '%.2f' % abs(float(info['percent_change'])) + '%' else: change = '%.2f' % abs(change) current = '%.2f' % float(info['current']) #TEXT midFrame = self.textToImageProf(ticker, current, change, arrow, font=ImageFont.load("./fonts/6x10.pil")) #IMAGE THE TEXT if all_stocks_settings['logos']: try: try: #load the tiny logo logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'tiny_stocks') logo = Image.open(os.path.join(logos_path, ticker + '.png')) except: # load the big logo and scale it logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'stocks') logo = Image.open(os.path.join(logos_path, ticker + '.png')) # half the size of the logo width, height = logo.size logo = logo.resize((int(width/2), int(height/2))) stitchedStock = self.stitchImage([logo,midFrame]) except Exception as e: stitchedStock = midFrame else: stitchedStock = midFrame image_list.append(stitchedStock) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() finalDisplayImage = self.stitchImage(image_list) self.blank = Image.new('RGB', (10, 32)) return finalDisplayImage def getNewsImage(self): f = open('csv/news_settings.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/news.png') image_list = [title_img] else: image_list = [] headline_font = ImageFont.load("./fonts/6x13.pil") source_font = ImageFont.load("./fonts/6x13.pil") headline_info = all_settings['headlines'] headlines = [] source_date_times = [] source = [] for i, hi in enumerate(headline_info): try: headline, source, date_time = hi date, time = date_time.split('T') time = time[:-1] source_date_time = source + ': ' + date + ' ' + time headline = headline.replace("^", ",") headline = headline.replace("’", "'") headline = headline.replace("‘", "'") headline = headline.replace('“', '"') headline = headline.replace('”', '"') headline = headline.replace('—', '-') headline = headline.replace('–', '-') headline = ''.join([h for h in headline if ord(h) < 256]) lst = headline.rsplit('-', 1) #remove source name at end of headline headline = lst[0] headline_img = self.textImage(headline, headline_font, matrix_height = True) source_img = self.textImage(source_date_time, source_font, r=255, g=255, b=0, matrix_height = True) try: logo_name = source.lower().replace(' ', '-') logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'news_logos') logo = Image.open(os.path.join(logos_path, logo_name + '.png')) except Exception as e: logo_name = 'default' logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'news_logos') logo = Image.open(os.path.join(logos_path, logo_name + '.png')) img = Image.new('RGB', (headline_img.size[0], 32)) img.paste(headline_img, (2, 0)) img.paste(source_img, (2,16)) img= self.stitchImage([logo,img]) image_list.append(img) image_list.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() news_image = self.stitchImage(image_list) return news_image def getNewsProfessional(self): f = open('csv/news_settings.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/news.png') image_list = [title_img] else: image_list = [] headline_font = ImageFont.load("./fonts/6x13.pil") source_font = ImageFont.load("./fonts/6x13.pil") headline_info = all_settings['headlines'] headlines = [] source_date_times = [] source = [] blank = Image.new('RGB', (0, 16)) for i, hi in enumerate(headline_info): try: headline, source, date_time = hi date, time = date_time.split('T') time = time[:-1] source_date_time = source + ': ' + date + ' ' + time headline = headline.replace("^", ",") headline = headline.replace("’", "'") headline = headline.replace("‘", "'") headline = headline.replace('“', '"') headline = headline.replace('”', '"') headline = headline.replace('—', '-') headline = headline.replace('–', '-') headline = ''.join([h for h in headline if ord(h) < 256]) lst = headline.rsplit('-', 1) #remove source name at end of headline headline = lst[0] headline_img = self.textImage(headline, headline_font, matrix_height = True) source_img = self.textImage(source_date_time+ ':', source_font, r=255, g=255, b=0, matrix_height = True) try: logo_name = source.lower().replace(' ', '-') logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'tiny_news') logo = Image.open(os.path.join(logos_path, logo_name + '.png')) except Exception as e: logo_name = 'default' logos_path = os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logos'), 'tiny_news') logo = Image.open(os.path.join(logos_path, logo_name + '.png')) width, height = logo.size #logo = logo.resize((int(width/2), int(height/2))) img = Image.new('RGB', (headline_img.size[0]+ source_img.size[0] + logo.size[0] +5, 32)) img.paste(headline_img, (source_img.size[0]+ logo.size[0] -5, 3)) img.paste(source_img, (2,3)) img= self.stitchImage([logo,img]) image_list.append(img) image_list.append(blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() news_image = self.stitchImage(image_list) return news_image def getLeagueImage(self, league=False, time = 'past'): if time in ['past', 'live']: filepath = 'csv/{}_games.json'.format(time) else: filepath = 'csv/upcoming_games.json' f = open(filepath, 'r') all_settings = json.load(f) f.close() title_img = self.openImage('feature_titles/sports_'+ time + '.png') if all_settings['title']: title_img = self.openImage('feature_titles/sports_{}.png'.format(time)) imgs = [title_img, self.blank] else: imgs = [] leagues_info = all_settings['leagues'] leagues = list(leagues_info.keys()) for league in leagues: try: x_offset = 0 img = Image.new('RGB', (10000, 32)) league_info = leagues_info[league] try: league_logo = Image.open('logos/sports/league_logos/{}.png'.format(league)).convert('RGB') img.paste(league_logo, (x_offset,0)) x_offset += league_logo.size[0] +self.blank.size[0] except: pass small_font = ImageFont.load("./fonts/5x7.pil") med_font = ImageFont.load("./fonts/7x14B.pil") large_font = ImageFont.load("./fonts/9x18B.pil") sports_info = self.readSportsCSV(league) buff_size = 25 for match in league_info: strHomeTeam = match['home_team'] strAwayTeam = match['away_team'] if time != 'future': intHomeScore = str(match['home_score']) intAwayScore = str(match['away_score']) dateEvent = match['date'].replace('-', '.') try: home_logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[strHomeTeam]['logo'])) except Exception as e: home_logo = self.textImage(strHomeTeam.replace(' ', '\n'), small_font, r = 255, g = 255, b = 255) try: away_logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[strAwayTeam]['logo'])) except Exception as e: away_logo = self.textImage(strAwayTeam.replace(' ', '\n'), small_font, r = 255, g = 255, b = 255) date_timage = self.textImage(dateEvent, small_font, r = 255, g = 255, b = 255) img.paste(home_logo, (x_offset,0)) x_offset += home_logo.size[0] + 2 if time == 'future': img.paste(date_timage, (x_offset+5, 0)) h_colour = mcolors.to_rgb(sports_info[strHomeTeam]['colour'].replace(' ', '')) a_colour = mcolors.to_rgb(sports_info[strAwayTeam]['colour'].replace(' ', '')) hc_timage = self.textImage(sports_info[strHomeTeam]['code'], med_font, r = int(h_colour[0]*255), g = int(h_colour[1]*255), b = int(h_colour[2]*255)) ac_timage = self.textImage(sports_info[strAwayTeam]['code'], med_font, r = int(a_colour[0]*255), g = int(a_colour[1]*255), b = int(a_colour[2]*255)) vs_timage = self.textImage('vs', med_font, r = 255, g = 255, b = 255, h_buff = 5) img.paste(hc_timage, (x_offset, 9)) img.paste(vs_timage, (x_offset + hc_timage.size[0], 9)) img.paste(ac_timage, (x_offset + hc_timage.size[0] + vs_timage.size[0], 9)) x_offset += max( date_timage.size[0], hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0]) else: score_image = self.textImage(intHomeScore + '-' + intAwayScore, large_font, h_buff = 5, r = 255, g = 255, b = 255) #vs_timage = self.textImage(sports_info[home_team]['code'] + 'vs' + sports_info[away_team]['code'], small_font, r = 255, g = 255, b = 255) h_colour = mcolors.to_rgb(sports_info[strHomeTeam]['colour'].replace(' ', '')) a_colour = mcolors.to_rgb(sports_info[strAwayTeam]['colour'].replace(' ', '')) hc_timage = self.textImage(sports_info[strHomeTeam]['code'], small_font, r = int(h_colour[0]*255), g = int(h_colour[1]*255), b = int(h_colour[2]*255)) ac_timage = self.textImage(sports_info[strAwayTeam]['code'], small_font, r = int(a_colour[0]*255), g = int(a_colour[1]*255), b = int(a_colour[2]*255)) vs_timage = self.textImage('vs', small_font, r = 255, g = 255, b = 255) if date_timage.size[0] > score_image.size[0]: img.paste(date_timage, (x_offset+2, 0)) img.paste(hc_timage, (x_offset+6, 9)) img.paste(vs_timage, (x_offset+5 + hc_timage.size[0], 9)) img.paste(ac_timage, (x_offset+6 + hc_timage.size[0] + vs_timage.size[0], 9)) img.paste(score_image, (x_offset + 2 + int((date_timage.size[0] - score_image.size[0])/2), 15)) else: img.paste(date_timage, (x_offset+1+int((score_image.size[0] - date_timage.size[0] )/2), 0)) vs_size = hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0] img.paste(hc_timage, (x_offset + 1 + int((score_image.size[0] - vs_size)/2), 9)) img.paste(vs_timage, (x_offset + int((score_image.size[0] - vs_size)/2) + hc_timage.size[0], 9)) img.paste(ac_timage, (x_offset+1 + int((score_image.size[0] - vs_size)/2) + hc_timage.size[0] + vs_timage.size[0], 9)) img.paste(score_image, (x_offset+1, 15)) x_offset += max( date_timage.size[0]+4, hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0]+4, 2 + int(score_image.size[0])) #img.paste(vs_timage, (x_offset+4, 9)) #if league == 'NHL': # #img.paste(round_timage, (x_offset+ 7, 8)) #x_offset += max(home_timage.size[0], away_timage.size[0], date_timage.size[0], round_timage.size[0], score_image.size[0]) img.paste(away_logo, (x_offset,0)) x_offset += away_logo.size[0] x_offset += buff_size img = img.crop((0,0,x_offset ,32)) imgs.append(img) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return self.stitchImage(imgs) def getLeagueTableImage(self, league = False): f = open('csv/league_tables.json', 'r') all_settings = json.load(f) f.close() leagues_info = all_settings['leagues'] leagues = list(leagues_info.keys()) if all_settings['title']: title_img = self.openImage('feature_titles/sports_team_stats.png') imgs = [title_img, self.blank] else: imgs = [] for league in leagues: try: x_offset = 0 img = Image.new('RGB', (10000, 32)) league_logo = Image.open('logos/sports/league_logos/{}.png'.format(league)).convert('RGB') img.paste(league_logo, (x_offset,0)) x_offset += league_logo.size[0] +self.blank.size[0] team_info = leagues_info[league] small_font = ImageFont.load("./fonts/5x7.pil") med_font = ImageFont.load("./fonts/8x13B.pil") large_font = ImageFont.load("./fonts/10x20.pil") #if league =='NHL': # read the NHl info from the csv, prem will need this as well sports_info = self.readSportsCSV(league) # gets colour and symbol info etc from csv buff_size = 20 for team in team_info: try: logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[team['name']]['logo'])) img.paste(logo, (x_offset, 0)) x_offset += logo.size[0] + 2 except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() name_timage = self.textImage(team['name'], med_font, r = 255, g = 255, b = 0) wins_timage = self.textImage('Wins:' + str(team['wins']), small_font, r = 0, g = 255, b = 0) loss_timage = self.textImage('Losses:' + str(team['loss']), small_font, r = 255, g = 0, b = 0) draw_timage = self.textImage('Draws:' + str(team['draw']), small_font, r = 0, g = 0, b = 255) #points_timage = self.textImage('Points:' + team['points'], small_font, r = 255, g = 255, b = 255) standing_timage = self.textImage('Standing:' + str(team['standing']), small_font, r = 255, g = 255, b = 255) img.paste(name_timage, (x_offset, -1)) img.paste(wins_timage, (x_offset, 12)) img.paste(loss_timage, (x_offset, 19)) img.paste(draw_timage, (x_offset, 26)) x_offset += max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) #img.paste(points_timage, (x_offset, 14)) img.paste(standing_timage, (x_offset, 22)) x_offset += standing_timage.size[0] if name_timage.size[0] > max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) + standing_timage.size[0]: x_offset += name_timage.size[0] - (max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) + standing_timage.size[0]) x_offset += buff_size img = img.crop((0,0,x_offset ,32)) imgs.append(img) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return self.stitchImage(imgs) def getLeagueTableProfessional(self, league = False): f = open('csv/league_tables.json', 'r') all_settings = json.load(f) f.close() leagues_info = all_settings['leagues'] leagues = list(leagues_info.keys()) if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/sports_team_stats.png') imgs = [title_img, self.blank] else: imgs = [] for league in leagues: try: x_offset = 0 img = Image.new('RGB', (10000, 32)) league_logo = Image.open('logos/sports/league_logos/{}.png'.format(league)).convert('RGB') width, height = league_logo.size league_logo2 = league_logo.resize((int(width/2), int(height/2))) img.paste(league_logo2, (x_offset,0)) x_offset += (league_logo2.size[0]+5) team_info = leagues_info[league] font = ImageFont.load("./fonts/6x10.pil") sports_info = self.readSportsCSV(league) buff_size = 20 for team in team_info: name_timage = self.textImage(team['name'].upper(), font, r = 255, g = 255, b = 0) wins_timage = self.textImage('W:' + str(team['wins']), font, r = 0, g = 255, b = 0) loss_timage = self.textImage('L:' + str(team['loss']), font, r = 255, g = 0, b = 0) draw_timage = self.textImage('D:' + str(team['draw']), font, r = 0, g = 0, b = 255) standing_timage = self.textImage('#' + str(team['standing']), font, r = 255, g = 255, b = 255) img.paste(standing_timage, (x_offset, 3)) x_offset += (standing_timage.size[0]) try: logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[team['name']]['logo'])) width, height = logo.size logo2 = logo.resize((int(width/2), int(height/2))) img.paste(logo2, (x_offset, 0)) x_offset += (logo2.size[0] + 3) except Exception as e: pass img.paste(name_timage, (x_offset, 3)) x_offset += (name_timage.size[0] +2) img.paste(wins_timage, (x_offset, 3)) x_offset += (wins_timage.size[0] +2) img.paste(loss_timage, (x_offset, 3)) x_offset += (loss_timage.size[0] +2) img.paste(draw_timage, (x_offset, 3)) x_offset += (draw_timage.size[0]+10) # x_offset += max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) #img.paste(points_timage, (x_offset, 14)) # img.paste(standing_timage, (x_offset, 22)) # x_offset += standing_timage.size[0] # if name_timage.size[0] > max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) + standing_timage.size[0]: # x_offset += name_timage.size[0] - (max( wins_timage.size[0], loss_timage.size[0], draw_timage.size[0]) + standing_timage.size[0]) # x_offset += buff_size x_offset += 25 img1 = img.crop((0,0,x_offset ,16)) imgs.append(img1) except Exception as e: pass return self.stitchImage(imgs) def getLeagueProfessional(self, league=False, time = 'future'): if time in ['past', 'live']: filepath = 'csv/{}_games.json'.format(time) else: filepath = 'csv/upcoming_games.json' f = open(filepath, 'r') all_settings = json.load(f) f.close() title_img = self.openImage('feature_titles/sports_'+ time + '.png') if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/sports_{}.png'.format(time)) imgs = [title_img, self.blank] else: imgs = [] leagues_info = all_settings['leagues'] leagues = list(leagues_info.keys()) for league in leagues: try: x_offset = 0 img = Image.new('RGB', (10000, 32)) league_info = leagues_info[league] #league logo try: league_logo = Image.open('logos/sports/league_logos/{}.png'.format(league)).convert('RGB') width, height = league_logo.size league_logo2 = league_logo.resize((int(width/2), int(height/2))) img.paste(league_logo2, (x_offset,0)) x_offset += (league_logo2.size[0]+10) except: pass font = ImageFont.load("./fonts/6x10.pil") small_font = ImageFont.load("./fonts/4x6.pil") sports_info = self.readSportsCSV(league) buff_size = 20 for match in league_info: strHomeTeam = match['home_team'] strAwayTeam = match['away_team'] if time != 'future': intHomeScore = str(match['home_score']) intAwayScore = str(match['away_score']) dateEvent = match['date'].replace('-', '.') try: home_logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[strHomeTeam]['logo'])) width1, height1 = home_logo.size home_logo1 = home_logo.resize((int(width1/2), int(height1/2))) except Exception as e: home_logo1 = self.textImage(strHomeTeam.replace(' ', '\n'), font, r = 255, g = 255, b = 255) try: away_logo = Image.open('logos/sports/{}/{}'.format(league, sports_info[strAwayTeam]['logo'])) width2, height2 = away_logo.size away_logo1 = away_logo.resize((int(width2/2), int(height2/2))) except Exception as e: away_logo1 = self.textImage(strAwayTeam.replace(' ', '\n'), font, r = 255, g = 255, b = 255) date_timage = self.textImage(dateEvent, small_font, r = 255, g = 255, b = 255) img.paste(home_logo1, (x_offset,0)) x_offset += (home_logo1.size[0] + 2) if time == 'future': img.paste(date_timage, (x_offset+5, 0)) h_colour = mcolors.to_rgb(sports_info[strHomeTeam]['colour'].replace(' ', '')) a_colour = mcolors.to_rgb(sports_info[strAwayTeam]['colour'].replace(' ', '')) hc_timage = self.textImage(sports_info[strHomeTeam]['code'], font, r = int(h_colour[0]*255), g = int(h_colour[1]*255), b = int(h_colour[2]*255)) ac_timage = self.textImage(sports_info[strAwayTeam]['code'], font, r = int(a_colour[0]*255), g = int(a_colour[1]*255), b = int(a_colour[2]*255)) vs_timage = self.textImage('vs', font, r = 255, g = 255, b = 255, h_buff = 5) img.paste(hc_timage, (x_offset, 5)) x_offset += hc_timage.size[0] img.paste(vs_timage, (x_offset, 5)) x_offset += vs_timage.size[0] img.paste(ac_timage, (x_offset, 5)) x_offset += ac_timage.size[0] #x_offset += max(date_timage.size[0], (hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0])) else: score_image = self.textImage(intHomeScore + '-' + intAwayScore, font, h_buff = 5, r = 255, g = 255, b = 255) h_colour = mcolors.to_rgb(sports_info[strHomeTeam]['colour'].replace(' ', '')) a_colour = mcolors.to_rgb(sports_info[strAwayTeam]['colour'].replace(' ', '')) hc_timage = self.textImage(sports_info[strHomeTeam]['code'], font, r = int(h_colour[0]*255), g = int(h_colour[1]*255), b = int(h_colour[2]*255)) ac_timage = self.textImage(sports_info[strAwayTeam]['code'], font, r = int(a_colour[0]*255), g = int(a_colour[1]*255), b = int(a_colour[2]*255)) img.paste(date_timage, (x_offset+20+int((score_image.size[0] - date_timage.size[0])/2),0)) img.paste(hc_timage, (x_offset, 5)) x_offset += hc_timage.size[0] img.paste(score_image, (x_offset, 5)) x_offset += score_image.size[0] img.paste(ac_timage, (x_offset, 5)) x_offset += ac_timage.size[0] # if date_timage.size[0] > score_image.size[0]: # img.paste(date_timage, (x_offset+2, 0)) # img.paste(hc_timage, (x_offset+6, 5)) # img.paste(vs_timage, (x_offset+5 + hc_timage.size[0], 5)) # img.paste(ac_timage, (x_offset+6 + hc_timage.size[0] + vs_timage.size[0], 5)) # img.paste(score_image, (x_offset + 2 + int((date_timage.size[0] - score_image.size[0])/2), 5)) # else: # img.paste(date_timage, (x_offset+1+int((score_image.size[0] - date_timage.size[0] )/2), 0)) # vs_size = hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0] # img.paste(hc_timage, (x_offset + 1 + int((score_image.size[0] - vs_size)/2), 5)) # img.paste(vs_timage, (x_offset + int((score_image.size[0] - vs_size)/2) + hc_timage.size[0], 5)) # img.paste(ac_timage, (x_offset+1 + int((score_image.size[0] - vs_size)/2) + hc_timage.size[0] + vs_timage.size[0], 5)) # img.paste(score_image, (x_offset+1, 5)) # x_offset += max( date_timage.size[0]+4, hc_timage.size[0] + vs_timage.size[0] + ac_timage.size[0]+4, 2 + int(score_image.size[0])) img.paste(away_logo1, (x_offset,0)) x_offset += away_logo1.size[0] x_offset += buff_size x_offset += 20 img = img.crop((0,0,x_offset ,16)) imgs.append(img) except: pass return self.stitchImage(imgs) def convertTemp(self,temp, setting): if setting == 'kelvin': temp = temp+ 273.15 elif setting == 'fahrenheit': temp = temp*9/5 + 32 return temp def getTodayWeatherImage(self): f = open('csv/current_weather.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/weather.png') imgs = [title_img, self.blank] else: imgs = [] current_weathers = all_settings['locations'] locations = list(current_weathers.keys()) for i, location in enumerate(locations): try: current_weather = current_weathers[location] small_font = ImageFont.load("./fonts/5x7.pil") large_font = ImageFont.load("./fonts/10x20.pil") location_img = self.textImage(location.upper(), small_font, r = 255, g = 255, b = 0) main = current_weather['main_weather'] if main == 'Clouds': main = current_weather['description'] if main == 'Rain': main = current_weather['description'] weather_ids = {'Clear': '01', 'few clouds': '02', 'scattered clouds': '03', 'broken clouds':'04', 'overcast clouds':'04', 'Drizzle':'09', 'Rain':'10', 'Thunderstorm':'11', 'Snow':'13', 'Mist': '50', 'Smoke': '50', 'Haze': '50', 'Dust': '50', 'Fog': '50', 'Sand': '50', 'Ash': '50', 'Squall': '50', 'Tornado': '50', 'light rain': '10', 'moderate rain': '10', 'heavy intensity rain': '10', 'very heavy rain': '10', 'extreme rain': '10', 'freezing rain': '13', 'light intensity shower rain': '09', 'shower rain': '09', 'heavy intensity shower rain': '09', 'ragged shower rain': '09'} weather_dir = './logos/weather_icons' weather_img = Image.open(weather_dir + '/weather_type_icons/' + weather_ids[main] + '.png') temp = self.convertTemp(current_weather['temp'], all_settings['temp']) feels_temp = self.convertTemp(current_weather['feels_like'], all_settings['temp']) temp_img = self.textImage(str("{0:.0f}".format(temp)), large_font) deg_img = self.textImage('o', small_font) main = current_weather['main_weather'] main_img = self.textImage(main.upper(), small_font) feels_img = self.textImage('Feels like:'.upper() + str("{0:.0f}".format(feels_temp)), small_font) min_img = self.textImage( "{0:.0f}".format(self.convertTemp(current_weather['min_temp'], all_settings['temp'])), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(self.convertTemp(current_weather['max_temp'], all_settings['temp'])), small_font, r=255, g=0, b=0) hum_img = Image.open(weather_dir + '/humidity.png') htext_img = self.textImage(str(current_weather['humidity']) + '%', small_font) uv_img = Image.open(weather_dir + '/uv.png') utext_img = self.textImage(str(round(current_weather['uv'], 1)) , small_font) weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months =['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] month = months[int(datetime.now().strftime('%m'))-1] date = str(int(datetime.now().strftime('%d'))) weekday = weekdays[datetime.today().weekday()] date_img = self.textImage((month + ' ' + date + ',' + weekday).upper(), small_font) rain_img = Image.open(weather_dir + '/rain-chance.png') rtext_img = self.textImage(str(int(current_weather['rain_chance']*100)) + '%', small_font) cloud_img = Image.open(weather_dir + '/clouds.png') ctext_img = self.textImage(str(current_weather['clouds']) + '%', small_font) wind_img = Image.open(weather_dir + '/wind.png') w_speed = current_weather['wind_speed']*3.6 w_unit = 'K/H' if all_settings["wind_speed"] == "miles/hour": w_speed = current_weather['wind_speed']*2.236936 w_unit = 'M/H' wtext_img = self.textImage("{0:.0f}".format(w_speed) + w_unit, small_font) wdir_img = self.textImage(self.degreesToCompass(current_weather['wind_direction']).upper(), small_font) vis_img = Image.open(weather_dir + '/visibility.png') vtext_img = self.textImage(str(round(current_weather['visibility']/1000, 1)) + 'km'.upper(), small_font) '------------------------------------------' img = Image.new('RGB', (1000, 32)) img.paste(weather_img, (5,9)) x_offset = 5 + weather_img.size[0] + 1 img.paste(main_img, (x_offset, 26)) img.paste(temp_img, (x_offset + main_img.size[0]//2 - temp_img.size[0]//2,9)) img.paste(deg_img, (x_offset + main_img.size[0]//2 - temp_img.size[0]//2 + temp_img.size[0], 8)) x_offset += max( main_img.size[0], temp_img.size[0] + deg_img.size[0]) img.paste(min_img, (x_offset - 0, 12)) img.paste(max_img, (x_offset - 0, 21)) x_offset += max(min_img.size[0], max_img.size[0]) + 2 img.paste(hum_img, ( x_offset - 1, 8)) img.paste(uv_img, ( x_offset - 1, 22)) img.paste(htext_img, (x_offset + hum_img.size[0], 10)) img.paste(utext_img, (x_offset + uv_img.size[0], 23)) x_offset += max(hum_img.size[0], uv_img.size[0]+2) x_offset += max(htext_img.size[0], utext_img.size[0]) + 6 img.paste(rain_img, (x_offset,8)) img.paste(cloud_img, (x_offset,20)) img.paste(ctext_img, (x_offset + cloud_img.size[0] + 2, 22)) img.paste(rtext_img, (x_offset + rain_img.size[0]+ 2, 10)) x_offset += max(cloud_img.size[0], rain_img.size[0])+6 x_offset += max(ctext_img.size[0], rtext_img.size[0])+6 img.paste(wind_img, (x_offset,8)) img.paste(vis_img, (x_offset,20)) img.paste(wtext_img, (x_offset + wind_img.size[0] + 2, 10)) img.paste(vtext_img, (x_offset + vis_img.size[0] + 2, 22)) x_offset += wind_img.size[0] + wtext_img.size[0] + 4 img.paste(wdir_img, (x_offset, 10)) img.paste(location_img, (5,0)) img.paste(feels_img, (location_img.size[0] + 10, 0)) img.paste(date_img, (location_img.size[0] + feels_img.size[0] + 15, 0)) img = img.crop((0,0,max(x_offset +wdir_img.size[0] + 4, location_img.size[0] + feels_img.size[0] + 15 + date_img.size[0]) ,32)) imgs.append(img) imgs.append(self.blank) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return self.stitchImage(imgs) def getTodayWeatherProfessional(self): f = open('csv/current_weather.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/weather.png') image_list = [title_img, Image.new('RGB', (3, 16))] else: image_list = [] current_weathers = all_settings['locations'] locations = list(current_weathers.keys()) weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months =['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] month = months[int(datetime.now().strftime('%m'))-1] date = str(int(datetime.now().strftime('%d'))) weekday = weekdays[datetime.today().weekday()] for i, location in enumerate(locations): try: img = Image.new('RGB', (1000, 32)) current_weather = current_weathers[location] small_font = ImageFont.load("./fonts/4x6.pil") font = ImageFont.load("./fonts/6x10.pil") large_font = ImageFont.load("./fonts/10x20.pil") main = current_weather['main_weather'] if main == 'Clouds': main = current_weather['description'] if main == 'Rain': main = current_weather['description'] weather_ids = {'Clear': '01', 'few clouds': '02', 'scattered clouds': '03', 'broken clouds':'04', 'overcast clouds':'04', 'Drizzle':'09', 'Rain':'10', 'Thunderstorm':'11', 'Snow':'13', 'Mist': '50', 'Smoke': '50', 'Haze': '50', 'Dust': '50', 'Fog': '50', 'Sand': '50', 'Ash': '50', 'Squall': '50', 'Tornado': '50', 'light rain': '10', 'moderate rain': '10', 'heavy intensity rain': '10', 'very heavy rain': '10', 'extreme rain': '10', 'freezing rain': '13', 'light intensity shower rain': '09', 'shower rain': '09', 'heavy intensity shower rain': '09', 'ragged shower rain': '09'} weather_dir = './logos/weather_icons' location_img = self.textImage(location.upper(), font, r = 255, g = 255, b = 0) img.paste(location_img, (5,3)) x_offset = location_img.size[0] + 8 date_img = self.textImage((month + ' ' + date + ',' + weekday).upper(), font) img.paste(date_img, (x_offset, 3)) x_offset += date_img.size[0] + 2 weather_img = Image.open(weather_dir + '/small_icons/' + weather_ids[main] + '.png') w, h = weather_img.size #weather_img = weather_img.resize((int(w/2), int(h/2))) main = current_weather['main_weather'] main_img = self.textImage(main.upper(), font) img.paste(main_img, (x_offset, 3)) x_offset += main_img.size[0] + 2 img.paste(weather_img, (x_offset,3)) x_offset += weather_img.size[0] + 2 temp = self.convertTemp(current_weather['temp'], all_settings['temp']) temp_img = self.textImage(str("{0:.0f}".format(temp)), font) img.paste(temp_img, (x_offset,3)) x_offset += temp_img.size[0]-3 deg_img = self.textImage('o', small_font) img.paste(deg_img, (x_offset+1, 1)) x_offset += deg_img.size[0] -2 min_img = self.textImage( "{0:.0f}".format(self.convertTemp(current_weather['min_temp'], all_settings['temp'])), small_font, r=0, g=0, b=255) img.paste(min_img, (x_offset+2, 2)) max_img = self.textImage( "{0:.0f}".format(self.convertTemp(current_weather['max_temp'], all_settings['temp'])), small_font, r=255, g=0, b=0) img.paste(max_img, (x_offset+2, 8)) x_offset += max_img.size[0] + 2 hum_img = Image.open(weather_dir + '/humidity.png') htext_img = self.textImage(str(current_weather['humidity']) + '%', font) uv_img = Image.open(weather_dir + '/uv.png') utext_img = self.textImage(str(round(current_weather['uv'], 1)), font) rain_img = Image.open(weather_dir + '/rain-chance.png') rtext_img = self.textImage(str(int(current_weather['rain_chance']*100)) + '%', font) cloud_img = Image.open(weather_dir + '/clouds.png') ctext_img = self.textImage(str(current_weather['clouds']) + '%', font) wind_img = Image.open(weather_dir + '/wind.png') w_speed = current_weather['wind_speed']*3.6 w_unit = 'K/H' if all_settings["wind_speed"] == "miles/hour": w_speed = current_weather['wind_speed']*2.236936 w_unit = 'M/H' wtext_img = self.textImage("{0:.0f}".format(w_speed) + w_unit, font) wdir_img = self.textImage(self.degreesToCompass(current_weather['wind_direction']).upper(), font) vis_img = Image.open(weather_dir + '/visibility.png') vtext_img = self.textImage(str(current_weather['visibility']/1000) + 'km', font) for image in [hum_img, htext_img, uv_img, utext_img, rain_img, rtext_img, cloud_img, ctext_img, wind_img, wtext_img, wdir_img, vis_img, vtext_img]: img.paste(image, (x_offset, 3)) x_offset += image.size[0] + 2 img = img.crop((0,0,x_offset +image.size[0] ,16)) image_list.append(img) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return self.stitchImage(image_list) def getDailyWeatherImageAlt(self): f = open( "csv/weather_location.txt", 'r' ) location = f.read() f.close() img = Image.new('RGB', (128, 32)) current_weather = json.load(open('csv/current_weather.json', 'r')) small_font = ImageFont.load("./fonts/5x7.pil") extra_small_font = ImageFont.load("./fonts/4x6.pil") large_font = ImageFont.load("./fonts/10x20.pil") location_img = self.textImage(location, extra_small_font, r = 255, g = 255, b = 0) main = current_weather['main_weather'] if main == 'Clouds': main = current_weather['description'] weather_ids = {'Clear': '01', 'few clouds': '02', 'scattered clouds': '03', 'broken clouds':'04', 'overcast clouds':'04', 'Drizzle':'09', 'Rain':'10', 'Thunderstorm':'11', 'Snow':'13', 'Mist': '50', 'Smoke': '50', 'Haze': '50', 'Dust': '50', 'Fog': '50', 'Sand': '50', 'Ash': '50', 'Squall': '50', 'Tornado': '50'} weather_dir = './logos/weather_icons' weather_img = Image.open(weather_dir + '/weather_type_icons/' + weather_ids[main] + '.png') temp_img = self.textImage(str("{0:.0f}".format(current_weather['temp'])), large_font) deg_img = self.textImage('o', small_font) min_img = self.textImage( "{0:.0f}".format(current_weather['min_temp']), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(current_weather['max_temp']), small_font, r=255, g=0, b=0) main = current_weather['main_weather'] main_img = self.textImage(main, small_font) weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months =['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] month = months[int(datetime.now().strftime('%m'))] date = str(int(datetime.now().strftime('%d'))) weekday = weekdays[datetime.today().weekday()] date_img = self.textImage(month + ' ' + date + ',' + weekday, extra_small_font) rain_img = Image.open(weather_dir + '/rain-chance.png') rtext_img = self.textImage(str(int(current_weather['rain_chance']*100)) + '%', extra_small_font) hum_img = Image.open(weather_dir + '/humidity.png') htext_img = self.textImage(str(current_weather['humidity']) + '%', extra_small_font) uv_img = Image.open(weather_dir + '/uv.png') utext_img = self.textImage(str(current_weather['uv']) , extra_small_font) wind_img = Image.open(weather_dir + '/wind.png') wtext_img = self.textImage(str(current_weather['wind_speed']) + 'm/s', extra_small_font) img.paste(location_img, (0,0)) img.paste(weather_img, (0,12)) img.paste(temp_img, (30,9)) img.paste(deg_img, (50, 8)) img.paste(min_img, (55, 10)) img.paste(main_img, (30, 26)) img.paste(max_img, (55, 19)) img.paste(date_img, (location_img.size[0], 1)) img.paste(rain_img, (75,0)) img.paste(rtext_img, (88, 1)) img.paste(hum_img, (102, 0)) img.paste(htext_img, (113, 1)) #img.paste(uv_img, ( 96, 0)) #img.paste(utext_img, (109, 0)) #img.paste(wind_img, (96,0)) #img.paste(wtext_img, (109,0)) img0 = img img = Image.new('RGB', (1000, 32)) daily_weather = json.load(open('csv/daily_weather.json', 'r')) #img.paste(date_img, (70, 0)) x_offset = 64 for i in range(0,len(daily_weather)-1): weekday = weekdays[(datetime.today().weekday() + i)%7] day_img = self.textImage( weekday, small_font) weather = daily_weather[i] main = weather['main_weather'] if main == 'Clouds': main = weather['description'] weather_img = Image.open(weather_dir + '/small_icons/' + weather_ids[main] + '.png') min_img = self.textImage( "{0:.0f}".format(weather['min_temp']), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(weather['max_temp']), small_font, r=255, g=0, b=0) img.paste(day_img, (x_offset +5, 9)) img.paste(weather_img, (x_offset +5, 16)) img.paste(min_img, (x_offset + 25, 10)) img.paste(max_img, (x_offset + 25, 20)) x_offset += 35 img1 = img.crop((64,0,x_offset ,32)) img1.save('display_images/weather.ppm') return img0, img1 def getDailyWeatherImage(self): f = open('csv/daily_weather.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/forecast.png') imgs = [title_img, self.blank] else: imgs = [] f = open('csv/daily_weather.json', 'r') daily_weathers = json.load(f) f.close() locations = list(daily_weathers['locations'].keys()) for i, location in enumerate(locations): try: img = Image.new('RGB', (1000, 32)) daily_weather = daily_weathers['locations'][location] small_font = ImageFont.load("./fonts/5x7.pil") extra_small_font = ImageFont.load("./fonts/4x6.pil") large_font = ImageFont.load("./fonts/10x20.pil") location_img = self.textImage(location.upper(), extra_small_font, r = 255, g = 255, b = 0) main = daily_weather[0]['main_weather'] if main == 'Clouds': main = daily_weather[0]['description'] if main == 'Rain': main = daily_weather[0]['description'] weather_ids = {'Clear': '01', 'few clouds': '02', 'scattered clouds': '03', 'broken clouds':'04', 'overcast clouds':'04', 'Drizzle':'09', 'Rain':'10', 'Thunderstorm':'11', 'Snow':'13', 'Mist': '50', 'Smoke': '50', 'Haze': '50', 'Dust': '50', 'Fog': '50', 'Sand': '50', 'Ash': '50', 'Squall': '50', 'Tornado': '50', 'light rain': '10', 'moderate rain': '10', 'heavy intensity rain': '10', 'very heavy rain': '10', 'extreme rain': '10', 'freezing rain': '13', 'light intensity shower rain': '09', 'shower rain': '09', 'heavy intensity shower rain': '09', 'ragged shower rain': '09'} weather_dir = './logos/weather_icons' weather_img = Image.open(weather_dir + '/weather_type_icons/' + weather_ids[main] + '.png') temp = self.convertTemp(daily_weather[0]['temp'], daily_weathers['temp']) min_temp = self.convertTemp(daily_weather[0]['min_temp'], daily_weathers['temp']) max_temp = self.convertTemp(daily_weather[0]['max_temp'], daily_weathers['temp']) temp_img = self.textImage(str("{0:.0f}".format(temp)), large_font) deg_img = self.textImage('o', small_font) min_img = self.textImage( "{0:.0f}".format(min_temp, daily_weathers['temp']), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(max_temp, daily_weathers['temp']), small_font, r=255, g=0, b=0) main = daily_weather[0]['main_weather'] main_img = self.textImage(main.upper(), small_font) weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months =['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] month = months[int(datetime.now().strftime('%m'))-1] date = str(int(datetime.now().strftime('%d'))) weekday = weekdays[datetime.today().weekday()] date_img = self.textImage((month + ' ' + date + ',' + weekday).upper(), extra_small_font) rain_img = Image.open(weather_dir + '/rain-chance.png') rtext_img = self.textImage(str(int(daily_weather[0]['rain_chance']*100)) + '%', extra_small_font) hum_img = Image.open(weather_dir + '/humidity.png') htext_img = self.textImage(str(daily_weather[0]['humidity']) + '%', extra_small_font) wind_img = Image.open(weather_dir + '/wind.png') wtext_img = self.textImage(str(daily_weather[0]['wind_speed']) + 'm/s'.upper(), extra_small_font) uv_img = Image.open(weather_dir + '/uv.png') utext_img = self.textImage(str(round(daily_weather[0]['uv'], 1)) , small_font) cloud_img = Image.open(weather_dir + '/clouds.png') ctext_img = self.textImage(str(daily_weather[0]['clouds']) + '%', small_font) wind_img = Image.open(weather_dir + '/wind.png') w_speed = daily_weather[0]['wind_speed']*3.6 w_unit = 'K/H' if daily_weathers['wind_speed'] == "miles/hour": w_speed = daily_weather[0]['wind_speed']*2.236936 w_unit = 'M/H' wtext_img = self.textImage("{0:.0f}".format(w_speed) + w_unit, small_font) wdir_img = self.textImage(self.degreesToCompass(daily_weather[0]['wind_direction']), small_font) vis_img = Image.open(weather_dir + '/visibility.png') vtext_img = self.textImage(str(round(daily_weather[0]['visibility']/1000, 1)) + 'km'.upper(), small_font) img.paste(location_img, (0,0)) x_offset = location_img.size[0]+2 img.paste(weather_img, (5,9)) x_offset = 5 + weather_img.size[0] + 1 img.paste(main_img, (x_offset, 26)) img.paste(temp_img, (x_offset + main_img.size[0]//2 - temp_img.size[0]//2,9)) img.paste(deg_img, (x_offset + main_img.size[0]//2 - temp_img.size[0]//2 + temp_img.size[0], 8)) x_offset += max( main_img.size[0], temp_img.size[0] + deg_img.size[0]) img.paste(min_img, (x_offset - 0, 12)) img.paste(max_img, (x_offset - 0, 21)) x_offset += max(min_img.size[0], max_img.size[0]) + 2 img.paste(date_img, (x_offset, 1)) x_offset += date_img.size[0]+2 img.paste(rain_img, (x_offset,0)) x_offset += rain_img.size[0]+2 img.paste(rtext_img, (x_offset, 1)) x_offset += rtext_img.size[0]+2 img.paste(hum_img, (x_offset, 0)) x_offset += hum_img.size[0]+2 img.paste(htext_img, (x_offset, 1)) x_offset+= htext_img.size[0]+2 img.paste(uv_img, ( x_offset, 0)) x_offset += uv_img.size[0]+2 img.paste(utext_img, (x_offset, 1)) x_offset += utext_img.size[0]+2 img.paste(cloud_img, (x_offset,0)) x_offset += cloud_img.size[0]+2 img.paste(ctext_img, (x_offset, 1)) x_offset += ctext_img.size[0]+2 img.paste(wind_img, (x_offset,0)) x_offset += wind_img.size[0]+2 img.paste(wtext_img, (x_offset, 1)) x_offset += wtext_img.size[0]+2 img.paste(wdir_img, (x_offset, 1)) x_offset+= wdir_img.size[0]+2 img.paste(vis_img, (x_offset,0)) x_offset+= vis_img.size[0]+2 img.paste(vtext_img, (x_offset, 1)) x_offset += vtext_img.size[0] +2 crop_x = x_offset #img.paste(uv_img, ( 96, 0)) #img.paste(utext_img, (109, 0)) #img.paste(wind_img, (96,0)) #img.paste(wtext_img, (109,0)) #img.paste(date_img, (70, 0)) x_offset = 77 for i in range(1,len(daily_weather)): weekday = weekdays[(datetime.today().weekday() + i)%7] day_img = self.textImage( weekday.upper(), small_font) weather = daily_weather[i] main = weather['main_weather'] if main == 'Clouds': main = weather['description'] if main == 'Rain': main = weather['description'] min_temp = self.convertTemp(weather['min_temp'], daily_weathers['temp']) max_temp = self.convertTemp(weather['max_temp'], daily_weathers['temp']) weather_img = Image.open(weather_dir + '/small_icons/' + weather_ids[main] + '.png') min_img = self.textImage( "{0:.0f}".format(min_temp), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(max_temp), small_font, r=255, g=0, b=0) img.paste(day_img, (x_offset +5, 9)) img.paste(weather_img, (x_offset +5, 16)) img.paste(min_img, (x_offset + 25, 10)) img.paste(max_img, (x_offset + 25, 18)) x_offset += 43 img1 = img.crop((0,0,max(x_offset, crop_x) ,32)) imgs.append(img1) imgs.append(self.blank) # add the image text except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return self.stitchImage(imgs) def getDailyWeatherProfessional(self): f = open('csv/daily_weather.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/forecast.png') image_list = [title_img, Image.new('RGB', (3, 16))] else: image_list = [] f = open('csv/daily_weather.json', 'r') daily_weathers = json.load(f) f.close() locations = list(daily_weathers['locations'].keys()) weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] months =['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] month = months[int(datetime.now().strftime('%m'))-1] date = str(int(datetime.now().strftime('%d'))) weekday = weekdays[datetime.today().weekday()] for i, location in enumerate(locations): try: img = Image.new('RGB', (1000, 32)) daily_weather = daily_weathers['locations'][location] small_font = ImageFont.load("./fonts/4x6.pil") font = ImageFont.load("./fonts/6x10.pil") large_font = ImageFont.load("./fonts/10x20.pil") main = daily_weather[0]['main_weather'] if main == 'Clouds': main = daily_weather[0]['description'] if main == 'Rain': main = daily_weather[0]['description'] weather_ids = {'Clear': '01', 'few clouds': '02', 'scattered clouds': '03', 'broken clouds':'04', 'overcast clouds':'04', 'Drizzle':'09', 'Rain':'10', 'Thunderstorm':'11', 'Snow':'13', 'Mist': '50', 'Smoke': '50', 'Haze': '50', 'Dust': '50', 'Fog': '50', 'Sand': '50', 'Ash': '50', 'Squall': '50', 'Tornado': '50', 'light rain': '10', 'moderate rain': '10', 'heavy intensity rain': '10', 'very heavy rain': '10', 'extreme rain': '10', 'freezing rain': '13', 'light intensity shower rain': '09', 'shower rain': '09', 'heavy intensity shower rain': '09', 'ragged shower rain': '09'} weather_dir = './logos/weather_icons' location_img = self.textImage(location.upper(), font, r = 255, g = 255, b = 0) img.paste(location_img, (5,3)) x_offset = location_img.size[0] + 8 date_img = self.textImage((month + ' ' + date + ',' + weekday).upper(), font) img.paste(date_img, (x_offset, 3)) x_offset += date_img.size[0] + 2 weather_img = Image.open(weather_dir + '/small_icons/' + weather_ids[main] + '.png') w, h = weather_img.size #weather_img = weather_img.resize((int(w/2), int(h/2))) main = daily_weather[0]['main_weather'] main_img = self.textImage(main.upper(), font) img.paste(main_img, (x_offset, 3)) x_offset += main_img.size[0] + 2 img.paste(weather_img, (x_offset,3)) x_offset += weather_img.size[0] + 2 temp = self.convertTemp(daily_weather[0]['temp'], daily_weathers['temp']) temp_img = self.textImage(str("{0:.0f}".format(temp)), font) img.paste(temp_img, (x_offset,3)) x_offset += temp_img.size[0]-3 deg_img = self.textImage('o', small_font) img.paste(deg_img, (x_offset+1, 1)) x_offset += deg_img.size[0] -2 min_img = self.textImage( "{0:.0f}".format(self.convertTemp(daily_weather[0]['min_temp'], daily_weathers['temp'])), small_font, r=0, g=0, b=255) img.paste(min_img, (x_offset+2, 2)) max_img = self.textImage( "{0:.0f}".format(self.convertTemp(daily_weather[0]['max_temp'], daily_weathers['temp'])), small_font, r=255, g=0, b=0) img.paste(max_img, (x_offset+2, 8)) x_offset += max_img.size[0] + 15 crop_x = x_offset for i in range(1,len(daily_weather)): weekday = weekdays[(datetime.today().weekday() + i)%7] day_img = self.textImage( weekday.upper(), font) weather = daily_weather[i] main = weather['main_weather'] if main == 'Clouds': main = weather['description'] if main == 'Rain': main = weather['description'] min_img = self.textImage( "{0:.0f}".format(self.convertTemp(weather['min_temp'], daily_weathers['temp'])), small_font, r=0, g=0, b=255) max_img = self.textImage( "{0:.0f}".format(self.convertTemp(weather['max_temp'], daily_weathers['temp'])), small_font, r=255, g=0, b=0) weather_img = Image.open(weather_dir + '/small_icons/' + weather_ids[main] + '.png') img.paste(day_img, (x_offset, 3)) x_offset += (day_img.size[0]) img.paste(weather_img, (x_offset, 3)) x_offset += (weather_img.size[0]+2) img.paste(min_img, (x_offset, 2)) img.paste(max_img, (x_offset, 8)) x_offset += (max(min_img.size[0], max_img.size[0])+5) x_offset += 35 img1 = img.crop((0,0,x_offset,16)) # img1 = img.crop((0,0,max(x_offset, crop_x) ,16)) image_list.append(img1) except Exception as e: pass return self.stitchImage(image_list) def readSportsCSV(self, league): team_info = {} f = open('csv/sports/{}/team_info.csv'.format(league), 'r') CSV = csv.reader(f) next(CSV) for row in CSV: team_info[row[0]] = {} team_info[row[0]]['id'] = row[1] team_info[row[0]]['code'] = row[2] team_info[row[0]]['logo'] = row[4] team_info[row[0]]['colour'] = row[3] f.close() return team_info def displayDailyWeatherAlt(self): img0, img1 = self.getDailyWeatherImageAlt() while True: self.setImage(img0, offset_x = 0, offset_y = 0) image = img1 img_width, img_height = image.size offset_x = 64 offset_y = 0 while offset_x > 64-img_width: offset_x -= 1 self.setImage(image, offset_x = offset_x, offset_y = offset_y, min_x = 64, min_y = 9) if offset_x + img_width < self.matrix.width: # if the image is ending self.setImage(image, offset_x = offset_x + img_width, offset_y = offset_y, min_x = 64, min_y = 9) try: msg = getInput() if msg == 'K': self.resetMatrix() return True self.process_msg(msg) except KeyboardInterrupt: sys.stdout.flush() pass time.sleep(self.delay*1.1) def getUserImages(self): f = open('csv/image_settings.json', 'r') all_settings = json.load(f) f.close() imgs = [] for ind,image in enumerate(all_settings['images']): try: img = self.openImage(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), image)) img.thumbnail((99999, 32)) if all_settings['title'] and ind == 0: title_img = self.openImage('feature_titles/images.png') imgs.append(self.stitchImage([title_img, img])) else: imgs.append(img) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() return imgs def getUserImagesProfessional(self): f = open('csv/image_settings.json', 'r') all_settings = json.load(f) f.close() if all_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/images.png') image_list = [title_img] else: image_list = [] blank = Image.new('RGB', (0, 16)) for i,image in enumerate(all_settings['images']): if (i == len(all_settings['images'])-1): try: user_image = self.openImage(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), image)) user_image.thumbnail((99999, 16)) #user_image.convert('RGB') img = Image.new('RGB', (user_image.size[0] + 5, 32)) img.paste(user_image, (0,0)) image_list.append(img) image_list.append(blank) except Exception as e: pass else: try: user_image = self.openImage(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), image)) user_image.thumbnail((99999, 16)) #user_image.convert('RGB') img = Image.new('RGB', (user_image.size[0] + 130, 32)) img.paste(user_image, (0,0)) image_list.append(img) image_list.append(blank) except Exception as e: pass return self.stitchImage(image_list) def getUserGIFs(self): f = open('csv/GIF_settings.json', 'r') all_settings = json.load(f) f.close() GIFs = [] for ind,fle in enumerate(all_settings['images']): try: GIF = Image.open(os.path.join(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_uploads'), fle)) frames = [] if ind == 0 and all_settings['title']: #title_img = self.openImage('feature_titles/gifs.png') for i, frame in enumerate(ImageSequence.Iterator(GIF)): frame = frame.convert('P') frame.thumbnail((128, 32),Image.NEAREST) #f = self.stitchImage([title_img, frame]) frames.append(frame) else: for i, frame in enumerate(ImageSequence.Iterator(GIF)): frame = frame.convert('P') frame.thumbnail((128, 32),Image.NEAREST) #frame = frame.resize((99999, 32)) #f = self.stitchImage([frame]) frames.append(frame) frames[0].save('./display_images/working_gif{}.gif'.format(str(ind)), save_all=True, append_images=frames[1:], loop=0, optimize = False) GIF = Image.open('./display_images/working_gif{}.gif'.format(str(ind))) GIFs.append(GIF) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close() #below code stitches title and GIF together # frames = [] # for i, frame in enumerate(ImageSequence.Iterator(gif)): # if all_settings['title']: # f = self.stitchImage([title_img, frame]) # else: # f = self.stitchImage([frame]) # frames.append(f) # frames[0].save('./display_images/Custom GIFs.gif', save_all=True, append_images=frames[1:], loop=0, optimize = False) return GIFs def getMoviesImage(self): f = open('csv/movie_settings.json', 'r') all_movie_settings = json.load(f) f.close() if all_movie_settings['title']: title_img = self.openImage('feature_titles/movies.png') image_list = [title_img] else: image_list = [] font = ImageFont.load("./fonts/6x13.pil") small_font = ImageFont.load("./fonts/5x8.pil") for movie in all_movie_settings['movies']: x_offset = 0 movie_title_img = self.textImage(movie['title'] + ' (' + movie['media_type'] + ')', font, r = 255, g = 180, b = 0) lang_img = self.textImage('Lan:' + movie['language'], small_font, r = 255, g = 0, b = 100) vote_img = self.textImage(movie['votes'], small_font, r = 255, g = 255, b = 255) star_img = Image.open('logos/star.png').convert('RGB') date_img = self.textImage(movie['date'], small_font, r = 0, g = 162, b = 255) try: logo = Image.open('logos/movies/' + movie['backdrop']) logo.thumbnail((9000,32)) logo.convert('P') except: logo = self.textImage('No Logo', small_font, r=255, g=255, b=255) x_offset += logo.size[0] + 3 genre_offset = 0 for genre in movie['genre']: genre_img = self.textImage(genre + ',', small_font, r = 255, g = 255, b = 255) genre_offset += genre_img.size[0] img = Image.new('RGB', (max(x_offset + movie_title_img.size[0], x_offset + date_img.size[0] + 3 + star_img.size[0] + vote_img.size[0] + 3, x_offset + date_img.size[0] + 3 + genre_offset) + 15, 32)) img.paste(logo, (0, 0)) img.paste(movie_title_img, (x_offset,0)) img.paste(date_img, (x_offset, 14)) img.paste(lang_img, (x_offset, 23)) x_offset += max(date_img.size[0], lang_img.size[0]) + 3 x_offset2 = x_offset img.paste(star_img, (x_offset2 , 14)) img.paste(vote_img, (x_offset2 + star_img.size[0] + 3, 14)) for genre in movie['genre'][:-1]: genre_img = self.textImage(genre + ',', small_font, r = 255, g = 255, b = 255) img.paste(genre_img, (x_offset2, 23)) x_offset2 += genre_img.size[0] else: genre_img2 = self.textImage(movie['genre'][-1], small_font, r = 255, g = 255, b = 255) img.paste(genre_img2, (x_offset2, 23)) x_offset2 += genre_img2.size[0] image_list.append(img) return self.stitchImage(image_list) def getMoviesProfessional(self): f = open('csv/movie_settings.json', 'r') all_movie_settings = json.load(f) f.close() if all_movie_settings['title']: title_img = self.openImage('feature_titles/small_feature_titles/movies.png') image_list = [title_img] else: image_list = [] font = ImageFont.load("./fonts/6x10.pil") small_font = ImageFont.load("./fonts/4x6.pil") for movie in all_movie_settings['movies']: x_offset = 0 movie_title_img = self.textImage(movie['title'] + ' (' + movie['media_type'] + ')', font, r = 255, g = 180, b = 0) lang_img = self.textImage('Lan:' + movie['language'], small_font, r = 255, g = 0, b = 100) vote_img = self.textImage(movie['votes'], small_font, r = 255, g = 255, b = 255) star_img = Image.open('logos/star.png').convert('RGB') date_img = self.textImage(movie['date'], small_font, r = 0, g = 162, b = 255) try: logo = Image.open('logos/movies/' + movie['backdrop']) logo.thumbnail((1000,16)) logo.convert('P') except: logo = self.textImage('No Logo', small_font, r=255, g=255, b=255) x_offset += logo.size[0] + 3 genre_offset = 0 # img = Image.new('RGB', (200,16)) for genre in movie['genre']: genre_img = self.textImage(genre + ',', small_font, r = 255, g = 255, b = 255) genre_offset += genre_img.size[0] img = Image.new('RGB', (max(x_offset + movie_title_img.size[0] + 3 + star_img.size[0] + 2 + vote_img.size[0] + 10, x_offset + date_img.size[0] + 7 + lang_img.size[0] + 7 + genre_offset + 10), 16)) img.paste(logo, (0, 0)) img.paste(movie_title_img, (x_offset,0)) x_offset2 = x_offset + movie_title_img.size[0] + 3 img.paste(star_img, (x_offset2, 1)) x_offset2 += star_img.size[0] + 2 img.paste(vote_img, (x_offset2, 2)) img.paste(date_img, (x_offset, 10)) x_offset += date_img.size[0] + 7 img.paste(lang_img, (x_offset, 10)) x_offset += lang_img.size[0] + 7 for genre in movie['genre'][:-1]: genre_img = self.textImage(genre + ',', small_font, r = 255, g = 255, b = 255) img.paste(genre_img, (x_offset, 10)) x_offset += genre_img.size[0] else: genre_img2 = self.textImage(movie['genre'][-1], small_font, r = 255, g = 255, b = 255) img.paste(genre_img2, (x_offset, 10)) x_offset += genre_img2.size[0] image_list.append(img) return self.stitchImage(image_list) def displayStocks(self): self.scrollImageTransition(['final.ppm', 'final.ppm'], offset_x = 0, offset_y = 0) def displayProfessional(self): forex = self.getForexProfessional() crypto = self.getCryptoProfessional() news = self.getNewsProfessional() stock = self.getStockProfessional() weather = self.getTodayWeatherProfessional() commodities = self.getCommoditiesProfessional() indices = self.getIndicesProfessional() daily_forecast = self.getDailyWeatherProfessional() sports_stats = self.getLeagueTableProfessional() sports_upcoming = self.getLeagueProfessional() sports_past = self.getLeagueProfessional() movies = self.getMoviesProfessional() messages = self.getUserMessagesProfessional() images = self.getUserImagesProfessional() x_offset = 0 news.paste(weather, (x_offset, 16)) x_offset += weather.size[0] news.paste(crypto, (x_offset, 16)) x_offset += crypto.size[0] news.paste(stock, (x_offset, 16)) x_offset += stock.size[0] news.paste(forex, (x_offset, 16)) x_offset += forex.size[0] news.paste(commodities, (x_offset, 16)) x_offset += commodities.size[0] news.paste(indices, (x_offset, 16)) x_offset += indices.size[0] news.paste(daily_forecast, (x_offset, 16)) x_offset += daily_forecast.size[0] news.paste(sports_stats, (x_offset, 16)) x_offset += sports_stats.size[0] news.paste(sports_upcoming, (x_offset, 16)) x_offset += sports_upcoming.size[0] news.paste(sports_past, (x_offset, 16)) x_offset += sports_past.size[0] news.paste(movies, (x_offset, 16)) x_offset += movies.size[0] news.paste(messages, (x_offset, 16)) x_offset += messages.size[0] news.paste(images, (x_offset, 16)) x_offset += images.size[0] self.double_buffer = self.matrix.CreateFrameCanvas() while True: kill = stock_ticker.scrollImage(news, offset_x = 128) if kill: break def process_msg(self, msg): if msg == 'S': # stocks self.scrollFunctionsAnimated(['stocks', 'stocks'], animation = 'traditional') elif msg == 'C': # crypto self.scrollFunctionsAnimated(['crypto', 'crypto'], animation = 'traditional') elif msg == 'F': # forex self.scrollFunctionsAnimated(['forex', 'forex'], animation = 'traditional') elif msg == 'N': #news self.scrollFunctionsAnimated(['news', 'news'], animation = 'traditional') # speed settings elif msg == 's': self.delay = 0.03 elif msg == 'm': self.delay = 0.02 elif msg == 'f': self.delay = 0.01 elif msg in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: # birghtness ettings self.brightness = (float(msg)+1)*10 self.matrix.brightness = self.brightness elif msg == 'T':# text self.scrollFunctionsAnimated(['text', 'text'], animation = 'traditional') elif msg == 'I': # image self.scrollFunctionsAnimated(['display_image', 'display_image'], animation = 'traditional') elif msg == 'G': # gif self.scrollFunctionsAnimated(['display_gif', 'display_gif'], animation = 'traditional') elif msg == 'W': # weather self.scrollFunctionsAnimated(['today_weather', 'today_weather'], animation = 'traditional') elif msg == 'D': # daily weather self.scrollFunctionsAnimated(['daily_weather', 'daily_weather'],animation = 'traditional') elif msg == 'P': # past league self.scrollFunctionsAnimated(['past_games', 'past_games'],animation = 'traditional') elif msg == 'l': # future league self.scrollFunctionsAnimated(['future_games', 'future_games'],animation = 'traditional') elif msg == 'L': # live game self.scrollFunctionsAnimated(['live_games', 'live_games'],animation = 'traditional') elif msg == 't': #legue tble self.scrollFunctionsAnimated(['league_table', 'league_table'],animation = 'traditional') elif msg == 'CO': #commodities self.scrollFunctionsAnimated(['commodities', 'commodities'],animation = 'traditional') elif msg == 'WI': #indices self.scrollFunctionsAnimated(['indices', 'indices'],animation = 'traditional') elif msg == 'MO': #movies self.scrollFunctionsAnimated(['movies', 'movies'],animation = 'traditional') elif msg == 'A': #everything #userSettings = ['display_gif', 'text', 'display_image', 'stocks', 'crypto', 'forex', 'today_weather', 'daily_weather', 'league_table', 'league_games', 'news'] # these wil be read from csv, just for demo #userSettings = [ 'daily_weather'] #userSettings = ['crypto', 'stocks'] # these wil be read from csv, just for demo #userSettings = [ 'display_image', 'news'] # these wil be read from csv, just for demo f = open('csv/display_settings.json', 'r') user_settings = json.load(f) f.close() if 'Professional'==user_settings[0] and len(user_settings[1][0])>0 and len(user_settings[1][1])>0: #if professional display self.scrollProfessionalAnimated(user_settings[1]) elif len(user_settings[1][0])>0 and 'Standard'==user_settings[0]: self.scrollFunctionsAnimated(user_settings[1][0], animation = 'down') elif msg == 'b': userSettings = json.load(open('csv/display_settings.json')) self.scrollProfessionalAnimated(userSettings) #self.displayProfessional() elif msg == '+': stock_ticker.scrollMultiple() elif msg == 'K': # kill self.resetMatrix() elif msg =='-': self.run_intro_screen() elif msg == '*': # # start_GIF = Image.open('./logos/startup_logo1.gif') self.displayGIF(start_GIF, delay = 0.02, repeat = False) #stock_ticker.setImage(start_image) time.sleep(2) self.resetMatrix() def run_intro_screen(self): dct = {"feature": "Custom Messages", "speed": "Medium", "animation": "Down", "title": False, "messages": [{"name": "welcome", "text": "Welcome to Fintic!", "text_colour": "White", "size": "Large", "background_colour": "Black"}, {"name": "get_started", "text": "To get started, connect your device to the \"Fintic Hotspot\" and access \"fintic.local:1024\" on your web browser. You can connect your ticker to Wi-Fi there.", "text_colour": "White", "size": "Small", "background_colour": "Black"}]} json.dump(dct, open('csv/message_settings.json', 'w')) self.scrollFunctionsAnimated(['Custom Messages'], repeat = True) if __name__ == '__main__': try: stock_ticker = StockTicker() while True: msg = getInput() stock_ticker.process_msg(msg) except Exception as e: pass # logf = open('log.txt', "a") # exc_type, exc_obj, exc_tb = sys.exc_info() # fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] # logf.write(str(e)) # logf.write('. file: ' + fname) # logf.write('. line: ' + str(exc_tb.tb_lineno)) # logf.write('. type: ' + str(exc_type)) # logf.write('\n ' + "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))) # logf.close()