From 00a05a1a6edaa65eb14c62fff3f9bd1a6a4ae03b Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 18 May 2019 09:28:29 +0200 Subject: [PATCH] Head start from @dicijr --- Calendar/CryptoInterface.py | 22 ++++++++++++++++++++++ Calendar/CryptoItem.py | 4 ++++ Calendar/CryptoListDesign.py | 27 +++++++++++++++++++++++++++ Calendar/CryptoPrices.py | 29 +++++++++++++++++++++++++++++ Calendar/DayHeaderDesign.py | 9 ++++++--- Calendar/DayListPanel.py | 24 +++++++++++++++++++++--- Calendar/DayRowDesign.py | 11 +++++++---- Calendar/DayViewPanel.py | 27 ++++++++++++++++++++++----- Calendar/E-Paper.py | 10 ++++++++-- Calendar/MonthOvPanel.py | 22 ++++++++++++++++++---- Calendar/settings.py.sample | 5 +++-- 11 files changed, 167 insertions(+), 23 deletions(-) create mode 100644 Calendar/CryptoInterface.py create mode 100644 Calendar/CryptoItem.py create mode 100644 Calendar/CryptoListDesign.py create mode 100644 Calendar/CryptoPrices.py diff --git a/Calendar/CryptoInterface.py b/Calendar/CryptoInterface.py new file mode 100644 index 0000000..fa3b7e5 --- /dev/null +++ b/Calendar/CryptoInterface.py @@ -0,0 +1,22 @@ +from DataSourceInterface import DataSourceInterface +from datetime import datetime, timezone, timedelta + +class CryptoInterface(DataSourceInterface): + def __init__(self): + self.crypto_prices = [] + + def reload(self): + if self.is_available() == False: + return + self.crypto_prices= self.__get_prices__() + self.sort_prices() + + def __get_prices__(self): + raise NotImplementedError("Functions needs to be implemented") + + def get_latest_prices(self): + self.crypto_prices = self.crypto_prices + return self.crypto_prices + + def sort_prices(self): + self.crypto_prices =self.crypto_prices diff --git a/Calendar/CryptoItem.py b/Calendar/CryptoItem.py new file mode 100644 index 0000000..83109fd --- /dev/null +++ b/Calendar/CryptoItem.py @@ -0,0 +1,4 @@ +class CryptoItem(object): + def __init__ (self): + self.name = None + self.value = None diff --git a/Calendar/CryptoListDesign.py b/Calendar/CryptoListDesign.py new file mode 100644 index 0000000..b5b9a8f --- /dev/null +++ b/Calendar/CryptoListDesign.py @@ -0,0 +1,27 @@ +from DesignEntity import DesignEntity +from TableDesign import TableDesign +from Assets import defaultfontsize +from CryptoPrices import CryptoPrices +from settings import coins as cryptos + + +class CryptoListDesign (DesignEntity): + def __init__ (self, size, coin, text_size = defaultfontsize): + super(CryptoListDesign, self).__init__(size) + self.coin = coin + self.__post_matrix__ = [] + self.text_size = text_size + + def __finish_image__ (self): + self.__fill_post_matrix__() + table_design = TableDesign(self.size, line_spacing=2, col_spacing=3, matrix=self.__post_matrix__, fontsize = self.text_size, mask=False, wrap=True, truncate_rows=True) + self.draw_design(table_design) + + def __fill_post_matrix__ (self): + price,name=CryptoPrices.__get_prices__(self.coin) + x=0 + while x < len(name): + row = name[x]+": $"+str(price[x]) + self.__post_matrix__.append(row) + x= x+1 + print(self.__post_matrix__) diff --git a/Calendar/CryptoPrices.py b/Calendar/CryptoPrices.py new file mode 100644 index 0000000..a31d950 --- /dev/null +++ b/Calendar/CryptoPrices.py @@ -0,0 +1,29 @@ +from CryptoInterface import CryptoInterface +from datetime import datetime, timedelta, date +import CryptoItem +import urllib.request +import json +import math + + +class CryptoPrices(CryptoInterface): + def __init__(self, coins): + self.coins = coins + super(CryptoPrices, self).__init__() + + def is_available(self): + if len(self.coins) > 0 and len(self.coins) < 8: + return True + else: + return False + + def __get_prices__(self): + price=[] + name=[] + for coin in self.coins: + data = urllib.request.urlopen("https://api.coingecko.com/api/v3/simple/price?ids="+coin+"&vs_currencies=USD").read() + dataJSON = json.loads(data.decode('utf-8')) + raw = dataJSON[coin]["usd"] + price.append(math.ceil(raw*100)/100) + name.append(coin) + return price,name diff --git a/Calendar/DayHeaderDesign.py b/Calendar/DayHeaderDesign.py index 4e69792..848be4e 100644 --- a/Calendar/DayHeaderDesign.py +++ b/Calendar/DayHeaderDesign.py @@ -59,6 +59,9 @@ class DayHeaderDesign (DesignEntity): def add_rssfeed (self, rss): pass + def add_crypto (self, crypto): + pass + def __finish_image__ (self): self.__draw_number_square__() self.__draw_month__() @@ -87,7 +90,7 @@ class DayHeaderDesign (DesignEntity): box_height = int(numberbox_height * self.size[1]) box_pos = (box_ypos + box_height + xpadding, box_ypos + ypadding) box_size = (int(monthbox_width * self.size[0]), box_height) - + month_name = self.date.strftime("%B") month = TextDesign(box_size, text=month_name, fontsize=font_size) month.pos = box_pos @@ -126,7 +129,7 @@ class DayHeaderDesign (DesignEntity): size = (box_height, weekdaybox_height * box_height) box_ypos = numberbox_ypos * self.size[1] pos = (box_ypos, box_ypos) - + week_day_name = self.date.strftime("%A") week_day = TextDesign(size, text=week_day_name, background_color=numberbox_background_color, color=numberbox_font_color, fontsize=font_size, horizontalalignment="center", verticalalignment = "center", font=weekday_font) week_day.pos = pos @@ -137,4 +140,4 @@ class DayHeaderDesign (DesignEntity): return (int(coordinates[0] * self.size[0]),int(coordinates[1] * self.size[1])) def __get_day_text__ (self): - return str(self.date.day) \ No newline at end of file + return str(self.date.day) diff --git a/Calendar/DayListPanel.py b/Calendar/DayListPanel.py index 3cec7a8..6530ce9 100644 --- a/Calendar/DayListPanel.py +++ b/Calendar/DayListPanel.py @@ -1,13 +1,14 @@ from PanelDesign import PanelDesign from Assets import colors from settings import general_settings -import calendar as callib +import calendar as callib from datetime import datetime, timedelta, date from PIL import ImageDraw from TextDesign import TextDesign from DayHeaderDesign import DayHeaderDesign from DayRowDesign import DayRowDesign from RssPostListDesign import RssPostListDesign +from CryptoListDesign import CryptoListDesign from settings import line_thickness todayheader_pos = (0,0) @@ -20,6 +21,7 @@ dayrowsarea_height = 1 - todayheader_size[1] dayrow_min_format = 50 / 384 dayrow_max_format = 70 / 384 rss_y_padding = 5 +crypto_y_padding = 5 class DayListPanel (PanelDesign): """Overview that focuses on the current day and @@ -48,6 +50,12 @@ class DayListPanel (PanelDesign): if general_settings["info-area"] is "rss": self.__draw_rss_infoarea__(rss) + def add_crypto (self, crypto): + for row in self.__day_rows__: + row.add_crypto(crypto) + if general_settings["info-area"] is "crypto": + self.__draw_crypto_infoarea__(crypto) + def __draw_rss_infoarea__ (self, rss): height = infoarea_replacedrowscount * self.dayrow_size[1] * self.size[1] - rss_y_padding ypos = self.size[1] - height @@ -58,6 +66,16 @@ class DayListPanel (PanelDesign): design.pos = pos self.draw_design(design) + def __draw_crypto_infoarea__ (self, crypto): + height = infoarea_replacedrowscount * self.dayrow_size[1] * self.size[1] - crypto_y_padding + ypos = self.size[1] - height + size = (self.size[0], height) + pos = (0, ypos) + + design = CryptoListDesign(size, crypto) + design.pos = pos + self.draw_design(design) + def __draw_day_rows__ (self): following_days = self.__get_following_days__() for i, date in enumerate(following_days): @@ -79,7 +97,7 @@ class DayListPanel (PanelDesign): row_height = max_area_height / self.dayrow_count self.dayrow_size = (1, row_height / self.size[1]) - if general_settings["info-area"] in ["rss"]: + if general_settings["info-area"] in ["rss"] or ["crypto"]: self.dayrow_count -= infoarea_replacedrowscount def __get_following_days__(self): @@ -108,4 +126,4 @@ class DayListPanel (PanelDesign): self.__draw_lines__() def __abs_co__(self, coordinates): - return (int(coordinates[0] * self.size[0]),int(coordinates[1] * self.size[1])) \ No newline at end of file + return (int(coordinates[0] * self.size[0]),int(coordinates[1] * self.size[1])) diff --git a/Calendar/DayRowDesign.py b/Calendar/DayRowDesign.py index 84fc631..63eac57 100644 --- a/Calendar/DayRowDesign.py +++ b/Calendar/DayRowDesign.py @@ -38,6 +38,9 @@ class DayRowDesign (DesignEntity): def add_rssfeed (self, rss): pass + def add_crypto (self, crypto): + pass + def __draw_event_list__ (self, calendar): number_width = daynumber_y_size[0] * self.size[1] ypos = eventlist_ypos * self.size[1] @@ -47,7 +50,7 @@ class DayRowDesign (DesignEntity): pos = (number_width + eventlist_xpadding, ypos) size = (self.size[0] - pos[0] - weather_width, self.size[1] - pos[1]) fontsize = eventlist_y_fontsize * self.size[1] - + events = calendar.get_day_events(self.date) rel_dates = [self.date for _ in range(len(events))] event_list = SingelDayEventListDesign(size, events, fontsize, event_prefix_rel_dates = rel_dates) @@ -56,7 +59,7 @@ class DayRowDesign (DesignEntity): def __draw_forecast__ (self, weather): forecast = weather.get_forecast_in_days(self.date.day - datetime.today().day) - + if forecast is None: return @@ -80,7 +83,7 @@ class DayRowDesign (DesignEntity): color = self.__get_day_color__() week_day_name = self.date.strftime("%a") - + week_day = TextDesign(size, text=week_day_name, font=font, color=color, fontsize=font_size, horizontalalignment="center", verticalalignment="top") week_day.pos = pos week_day.mask = False @@ -112,4 +115,4 @@ class DayRowDesign (DesignEntity): elif week_starts_on == "Sunday" and self.date.strftime("%w") == "6": return colors["hl"] else: - return colors["fg"] \ No newline at end of file + return colors["fg"] diff --git a/Calendar/DayViewPanel.py b/Calendar/DayViewPanel.py index 88e6b9f..124f21f 100644 --- a/Calendar/DayViewPanel.py +++ b/Calendar/DayViewPanel.py @@ -2,18 +2,20 @@ from PanelDesign import PanelDesign from datetime import datetime, timedelta, date from DayHeaderDesign import DayHeaderDesign from HourListDesign import HourListDesign -from settings import general_settings, line_thickness +from settings import general_settings from RssPostListDesign import RssPostListDesign from PIL import ImageDraw from Assets import colors from EventListDesign import EventListDesign +from CryptoListDesign import CryptoListDesign + header_size = (1, 0.2) hourlist_size = (1, 1 - header_size[1]) default_shownhours_count = 12 infoarea_replaced_hours = 4 -infoarea_borderline_width = line_thickness +infoarea_borderline_width = 1 infoarea_padding = 5 class DayViewPanel (PanelDesign): @@ -47,6 +49,11 @@ class DayViewPanel (PanelDesign): self.__draw_rss_feed__(rss) self.__draw_infoarea_line__() + def add_cryptofeed (self, crypto): + if general_settings["info-area"] == "crypto": + self.__draw_crypto_feed__(crypto) + self.__draw_infoarea_line__() + def __draw_infoarea_line__(self): height = infoarea_replaced_hours * self.__hourlist__.row_size[1] ypos = self.size[1] - height @@ -64,6 +71,16 @@ class DayViewPanel (PanelDesign): rss.pos = pos self.draw_design(rss) + def __draw_crypto_feed__(self, crypto): + height = infoarea_replaced_hours * self.__hourlist__.row_size[1] - infoarea_padding + size = (self.size[0], height) + pos = (0, self.size[1] - size[1]) + + crypto = CryptoListDesign(size, crypto) + crypto.pos = pos + self.draw_design(crypto) + + def __draw_event_list__(self, calendar): height = infoarea_replaced_hours * self.__hourlist__.row_size[1] - infoarea_padding size = (self.size[0], height) @@ -88,14 +105,14 @@ class DayViewPanel (PanelDesign): start, end = self.__get_current_hour_range__() size = self.__abs_co__(hourlist_size) size = (size[0], size[1] * self.shownhours_count / default_shownhours_count) - + self.__hourlist__ = HourListDesign(size, start, end) self.__hourlist__.pos = (0, self.__header__.size[1]) def __get_current_hour_range__(self): start_hour = datetime.now().hour additional_hours = self.shownhours_count - 1 - + if start_hour + additional_hours > 23: start_hour = 23 - additional_hours @@ -126,4 +143,4 @@ class DayViewPanel (PanelDesign): today = date.today() return dt.day == today.day and \ dt.month == today.month and \ - dt.year == today.year \ No newline at end of file + dt.year == today.year diff --git a/Calendar/E-Paper.py b/Calendar/E-Paper.py index a43bcc2..50b780d 100644 --- a/Calendar/E-Paper.py +++ b/Calendar/E-Paper.py @@ -13,7 +13,7 @@ from Assets import path from LoopTimer import LoopTimer import locale from DebugConsole import DebugConsole -from settings import datetime_encoding, language, render_to_display, render_to_file, display_colours, location, api_key, owm_paid_subscription, choosen_design, ical_urls, highlighted_ical_urls, rss_feeds, update_interval, calibrate_hours +from settings import datetime_encoding, language, render_to_display, render_to_file, display_colours, location, api_key, owm_paid_subscription, choosen_design, ical_urls, highlighted_ical_urls, rss_feeds, update_interval, calibrate_hours,coins from MonthOvPanel import MonthOvPanel from DayListPanel import DayListPanel from DayViewPanel import DayViewPanel @@ -22,6 +22,7 @@ from AgendaListPanel import AgendaListPanel import OwmForecasts import IcalEvents import RssParserPosts +import CryptoPrices all_locales = locale.locale_alias if language.lower() not in all_locales.keys(): @@ -61,6 +62,7 @@ def main(): owm = OwmForecasts.OwmForecasts(location, api_key, paid_api=owm_paid_subscription) events_cal = IcalEvents.IcalEvents(ical_urls, highlighted_ical_urls) rss = RssParserPosts.RssParserPosts(rss_feeds) + coin = CryptoPrices.CryptoPrices(coins) while True: loop_timer.begin_loop() @@ -71,11 +73,15 @@ def main(): for output in output_adapters: output.calibrate() - if choosen_design in available_panels.keys(): + if choosen_design in available_panels.keys(): design = available_panels[choosen_design]((epd.width, epd.height)) else: raise ImportError("choosen_design must be valid (" + choosen_design + ")") + debug.print_line('Getting crypto prices') + coin.reload() + design.add_crypto(coin) + debug.print_line("Fetching weather information from open weather map") owm.reload() design.add_weather(owm) diff --git a/Calendar/MonthOvPanel.py b/Calendar/MonthOvPanel.py index 29263e1..b580056 100644 --- a/Calendar/MonthOvPanel.py +++ b/Calendar/MonthOvPanel.py @@ -11,7 +11,9 @@ from EllipseDesign import EllipseDesign from MonthBlockDesign import MonthBlockDesign, daynumberboxsize from EventListDesign import EventListDesign from RssPostListDesign import RssPostListDesign -from settings import general_settings, line_thickness +from settings import general_settings +from CryptoListDesign import CryptoListDesign + weatherheadersize = (1,0.113) monthboxsize = (1, 0.085) @@ -65,6 +67,10 @@ class MonthOvPanel (PanelDesign): if general_settings["info-area"] is "rss": self.__draw_rss_post_list_to_bottom__(rss) + def add_crypto (self, crypto): + if general_settings["info-area"] is "crypto": + self.__draw_crypto_post_list_to_bottom__(crypto) + def add_calendar (self, calendar): if general_settings["highlight-event-days"]: month_events = list(set([ (event.begin_datetime.day, event.begin_datetime.month, event.begin_datetime.year) for event in calendar.get_month_events()])) @@ -82,6 +88,14 @@ class MonthOvPanel (PanelDesign): info_list.pos = (int(month_pos[0]), month_pos[1] + month_height + self.weather_header_height) self.draw_design(info_list) + def __draw_crypto_post_list_to_bottom__ (self, crypto): + month_pos = self.__abs_pos__(monthovposition) + month_height = self.month_block.get_real_height() + size = (self.size[0], self.size[1] - (month_pos[1] + month_height + self.weather_header_height)) + info_list = CryptoListDesign(size, crypto) + info_list.pos = (int(month_pos[0]), month_pos[1] + month_height + self.weather_header_height) + self.draw_design(info_list) + def __draw_event_list_to_bottom__ (self, calendar): month_pos = self.__abs_pos__(monthovposition) month_height = self.month_block.get_real_height() @@ -110,7 +124,7 @@ class MonthOvPanel (PanelDesign): def __draw_seperator__ (self): """Draw a line seperating the weather and Calendar section""" - ImageDraw.Draw(self.__image__).line([ self.__abs_pos__(seperatorplace), self.__abs_pos__((1, seperatorplace[1])) ], fill='red', width=line_thickness) + ImageDraw.Draw(self.__image__).line([ self.__abs_pos__(seperatorplace), self.__abs_pos__((1, seperatorplace[1])) ], fill='red', width=5) def __draw_month_name__ (self): """Draw the icon with the current month's name""" @@ -126,7 +140,7 @@ class MonthOvPanel (PanelDesign): pos = self.__get_week_day_pos__(day_of_week) txt.pos = (pos[0], pos[1] + weekdaytextpadding * self.size[1]) self.draw_design(txt) - + self.__draw_highlight_box__(self.__abs_pos__(weekrownameboxsize), self.__get_week_day_pos__(self.__get_day_of_week__(datetime.now())), width=1) def __get_week_day_pos__ (self, day_of_week): @@ -158,4 +172,4 @@ class MonthOvPanel (PanelDesign): return weekdays def __get_day_of_week__ (self, date): - return self.__week_days__.index(date.strftime("%a")) \ No newline at end of file + return self.__week_days__.index(date.strftime("%a")) diff --git a/Calendar/settings.py.sample b/Calendar/settings.py.sample index 8327d14..77e9c39 100644 --- a/Calendar/settings.py.sample +++ b/Calendar/settings.py.sample @@ -21,13 +21,14 @@ datetime_encoding = "UTF-8" # UTF-8 units = "metric" #aviation (celcius,degrees/knots), metric (celcius,kmh), imperial(f,mph) hours = "24" update_interval = 60 +coins=["bitcoin","litecoin","ethereum","binancecoin"] #Max might be 7 once fixed. """DESIGN""" font_size = 14 # does not affect every text font_boldness = "semibold" # extralight, light, regular, semibold, bold, extrabold -choosen_design = "month-overview" # month-overview, day-list, day-view, agenda-list, month-view -line_thickness = 1 # 1-3 Thickness advised +line_thickness = 1 #1-3 Thickness advised // Default = 1 // day-list view only! +choosen_design = "day-list" # month-overview, day-list, day-view, agenda-list, month-view general_settings = { # General settings that designs may use "info-area" : "rss", # empty, events, rss "highlight-event-days" : True,