diff --git a/inkycal/__init__.py b/inkycal/__init__.py index fb1e487..e5bfd50 100644 --- a/inkycal/__init__.py +++ b/inkycal/__init__.py @@ -7,8 +7,8 @@ from inkycal.display import Display import inkycal.modules.inkycal_agenda import inkycal.modules.inkycal_calendar import inkycal.modules.inkycal_weather -import inkycal.modules.inkycal_rss -#import inkycal.modules.inkycal_image +import inkycal.modules.inkycal_feeds +# import inkycal.modules.inkycal_image # import inkycal.modules.inkycal_server # Main file diff --git a/inkycal/config/__init__.py b/inkycal/config/__init__.py index 4d83e1d..9109855 100644 --- a/inkycal/config/__init__.py +++ b/inkycal/config/__init__.py @@ -1,2 +1 @@ -from .settings_parser import Settings from .layout import Layout diff --git a/inkycal/config/layout.py b/inkycal/config/layout.py index 9404019..29976f0 100644 --- a/inkycal/config/layout.py +++ b/inkycal/config/layout.py @@ -124,5 +124,4 @@ class Layout: if __name__ == '__main__': print('running {0} in standalone/debug mode'.format( - os.path.basename(__file__).split('.py')[0])) - + os.path.basename(__file__).split('.py')[0])) \ No newline at end of file diff --git a/inkycal/config/settings_parser.py b/inkycal/config/settings_parser.py deleted file mode 100644 index b4f19e0..0000000 --- a/inkycal/config/settings_parser.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -""" -Json settings parser for inkycal project -Copyright by aceisace -""" -from inkycal.config.layout import Layout -import json -import os -import logging -from jsmin import jsmin - -logger = logging.getLogger('settings') -logger.setLevel(level=logging.DEBUG) - -class Settings: - """Load and validate settings from the settings file""" - - _supported_languages = ['en', 'de', 'ru', 'it', 'es', 'fr', 'el', 'sv', 'nl', - 'pl', 'ua', 'nb', 'vi', 'zh_tw', 'zh-cn', 'ja', 'ko'] - _supported_units = ['metric', 'imperial'] - _supported_hours = [12, 24] - _supported_update_interval = [10, 15, 20, 30, 60] - _supported_display_orientation = ['normal', 'upside_down'] - _supported_models = [ - 'epd_7_in_5_v2_colour', 'epd_7_in_5_v2', - 'epd_7_in_5_colour', 'epd_7_in_5', - 'epd_5_in_83_colour','epd_5_in_83', - 'epd_4_in_2_colour', 'epd_4_in_2', - '9_in_7' - ] - - def __init__(self, settings_file_path): - """Load settings from path (folder or settings.json file) - Set show_info_section to False to hide the info section""" - try: - if settings_file_path.endswith('settings.json'): - folder = settings_file_path.split('/settings.json')[0] - else: - folder = settings_file_path - - os.chdir(folder) - if os.path.exists('settings.jsonc'): - with open("settings.jsonc") as jsonc_file: - # minify in order to remove comments - minified = jsmin(jsonc_file.read()) - - # remove known invalid json (comma followed by closing accolades) - minified = minified.replace(",}","}") - settings = json.loads(minified) - self._settings = settings - else: - with open("settings.json") as file: - settings = json.load(file) - self._settings = settings - - except FileNotFoundError: - print('No settings file found in specified location') - - # Validate the settings - self._validate() - - # Get the height-percentages of the modules - if self.info_section == True: - self.Layout = Layout(model=self.model, use_info_section = True) - else: - self.Layout = Layout(model=self.model, use_info_section = False) - - all_heights = [_['height'] for _ in self._settings['panels']] - num_modules = len(self.active_modules()) - - - # check if height have (or have not) been provided for all modules - if len(all_heights) == num_modules: - - # If no height is provided, use default values - if list(set(all_heights)) == [None]: - self.Layout.create_sections() - - # if all heights are specified, use given values - else: - logger.info('Setting section height according to settings file') - - to_decimal = lambda percentage: percentage/100 - - top_height = [to_decimal(_['height']) for _ in - self._settings['panels'] if _['location'] == 'top'] - - middle_height = [to_decimal(_['height']) for _ in - self._settings['panels'] if _['location'] == 'middle'] - - bottom_height = [to_decimal(_['height']) for _ in - self._settings['panels'] if _['location'] == 'bottom'] - - self.Layout.create_sections( - top_section = top_height[0] if top_height else 0, - middle_section = middle_height[0] if middle_height else 0, - bottom_section = bottom_height[0] if bottom_height else 0) - - # If only some heights were defined, raise an error - else: - print("Section height is not defined for all sections.") - print("Please leave height empty for all modules") - print("OR specify the height for all sections") - raise Exception('Module height is not specified in all modules!') - - - def _validate(self): - """Validate the basic config""" - settings = self._settings - - required = ['language', 'units', 'hours', 'model', 'calibration_hours', - 'display_orientation', 'info_section'] - - # Check if all required settings exist - for param in required: - if not param in settings: - raise Exception ( - 'required parameter: `{0}` not found in settings file!'.format(param)) - - # Attempt to parse the parameters - self.language = settings['language'] - self.units = settings['units'] - self.hours = settings['hours'] - self.model = settings['model'] - self.update_interval = settings['update_interval'] - self.calibration_hours = settings['calibration_hours'] - self.display_orientation = settings['display_orientation'] - self.info_section = settings['info_section'] - - # Validate the parameters - if (not isinstance(self.language, str) or self.language not in - self._supported_languages): - print('Language not supported, switching to fallback, en') - self.language = 'en' - - if (not isinstance(self.units, str) or self.units not in - self._supported_units): - print('units not supported, switching to fallback, metric') - self.units = 'metric' - - if (not isinstance(self.hours, int) or self.hours not in - self._supported_hours): - print('hour-format not supported, switching to fallback, 24') - self.hours = 24 - - if (not isinstance(self.model, str) or self.model not in - self._supported_models): - print('model not supported, switching to fallback, epd_7_in_5') - self.model = 'epd_7_in_5' - - if (not isinstance(self.update_interval, int) or self.update_interval - not in self._supported_update_interval): - print('update-interval not supported, switching to fallback, 60') - self.update_interval = 60 - - if (not isinstance(self.calibration_hours, list)): - print('calibration_hours not supported, switching to fallback, [0,12,18]') - self.calibration_hours = [0,12,18] - - if (not isinstance(self.display_orientation, str) or self.display_orientation not in - self._supported_display_orientation): - print('display orientation not supported, switching to fallback, normal') - self.display_orientation = 'normal' - - if (not isinstance(self.info_section, bool)): - print('info_section must be True/False. Switching to fallback: False') - self.info_section = False - - print('Settings file OK!') - - def active_modules(self): - modules = [section['type'] for section in self._settings['panels']] - return modules - - def common_config(self): - common_config = { - 'language' : self.language, 'units' : self.units, 'hours' : self.hours - } - return common_config - - - def get_config(self, module_name): - """Ge the config of this module (size, config)""" - if module_name not in self.active_modules(): - print('No config is available for this module') - else: - for section in self._settings['panels']: - if section['type'] == module_name: - config = section['config'] - size = self.Layout.get_size(self.get_position(module_name)) - return {'size':size, 'config': {**config, **self.common_config()}} - - def get_position(self, module_name): - """Get the position of this module's image on the display""" - if module_name not in self.active_modules(): - print('No position is available for this module') - else: - for section in self._settings['panels']: - if section['type'] == module_name: - position = section['location'] - return position - -if __name__ == '__main__': - print('running {0} in standalone/debug mode'.format( - os.path.basename(__file__).split('.py')[0])) - diff --git a/inkycal/custom/functions.py b/inkycal/custom/functions.py index 914fa0d..b38f4ed 100644 --- a/inkycal/custom/functions.py +++ b/inkycal/custom/functions.py @@ -11,6 +11,8 @@ from urllib.request import urlopen import os import time +logger = logging.getLogger('inkycal_custom') +logger.setLevel(level=logging.INFO) # Get the path to the Inkycal folder top_level = os.path.dirname( @@ -107,11 +109,11 @@ def write(image, xy, box_size, text, font=None, **kwargs): # Truncate text if text is too long so it can fit inside the box if (text_width, text_height) > (box_width, box_height): - logging.debug(('truncating {}'.format(text))) + logger.debug(('truncating {}'.format(text))) while (text_width, text_height) > (box_width, box_height): text=text[0:-1] text_width, text_height = font.getsize(text)[0], font.getsize('hg')[1] - logging.debug((text)) + logger.debug((text)) # Align text to desired position if alignment == "center" or None: diff --git a/inkycal/display/epaper.py b/inkycal/display/epaper.py deleted file mode 100644 index 4e4eb7c..0000000 --- a/inkycal/display/epaper.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -""" -Inky-Calendar epaper functions -Copyright by aceisace -""" -from importlib import import_module -from PIL import Image - - -class Display: - """Display class for inkycal - Handles rendering on display""" - - def __init__(self, epaper_model): - """Load the drivers for this epaper model""" - if 'colour' in epaper_model: - self.supports_colour = True - else: - self.supports_colour = False - - try: - driver_path = 'inkycal.display.drivers.{}'.format(epaper_model) - driver = import_module(driver_path) - self._epaper = driver.EPD() - self.model_name = epaper_model - - except ImportError: - raise Exception('This module is not supported. Check your spellings?') - - except FileNotFoundError: - raise Exception('SPI could not be found. Please check if SPI is enabled') - - def render(self, im_black, im_colour = None): - """Render an image on the epaper - im_colour is required for three-colour epapers""" - - epaper = self._epaper - - if self.supports_colour == False: - print('Initialising..', end = '') - epaper.init() - # For the 9.7" ePaper, the image needs to be flipped by 90 deg first - # The other displays flip the image automatically - if self.model_name == "9_in_7": - im_black.rotate(90, expand=True) - print('Updating display......', end = '') - epaper.display(epaper.getbuffer(im_black)) - print('Done') - - elif self.supports_colour == True: - if not im_colour: - raise Exception('im_colour is required for coloured epaper displays') - print('Initialising..', end = '') - epaper.init() - print('Updating display......', end = '') - epaper.display(epaper.getbuffer(im_black), epaper.getbuffer(im_colour)) - print('Done') - - print('Sending E-Paper to deep sleep...', end = '') - epaper.sleep() - print('Done') - - def calibrate(self, cycles=3): - """Flush display with single colour to prevent burn-ins (ghosting) - cycles -> int. How many times should each colour be flushed? - recommended cycles = 3""" - - epaper = self._epaper - epaper.init() - - white = Image.new('1', (epaper.width, epaper.height), 'white') - black = Image.new('1', (epaper.width, epaper.height), 'black') - - print('----------Started calibration of ePaper display----------') - if self.supports_colour == True: - for _ in range(cycles): - print('Calibrating...', end= ' ') - print('black...', end= ' ') - epaper.display(epaper.getbuffer(black), epaper.getbuffer(white)) - print('colour...', end = ' ') - epaper.display(epaper.getbuffer(white), epaper.getbuffer(black)) - print('white...') - epaper.display(epaper.getbuffer(white), epaper.getbuffer(white)) - print('Cycle {0} of {1} complete'.format(_+1, cycles)) - - if self.supports_colour == False: - for _ in range(cycles): - print('Calibrating...', end= ' ') - print('black...', end = ' ') - epaper.display(epaper.getbuffer(black)) - print('white...') - epaper.display(epaper.getbuffer(white)), - print('Cycle {0} of {1} complete'.format(_+1, cycles)) - - print('-----------Calibration complete----------') - epaper.sleep() - - diff --git a/inkycal/modules/__init__.py b/inkycal/modules/__init__.py index fec80e7..c642da6 100644 --- a/inkycal/modules/__init__.py +++ b/inkycal/modules/__init__.py @@ -1,5 +1,5 @@ from .inkycal_agenda import Agenda from .inkycal_calendar import Calendar from .inkycal_weather import Weather -from .inkycal_rss import RSS +from .inkycal_feeds import RSS #from .inkycal_image import Image diff --git a/inkycal/modules/inkycal_agenda.py b/inkycal/modules/inkycal_agenda.py index 581e1ff..106a2ee 100644 --- a/inkycal/modules/inkycal_agenda.py +++ b/inkycal/modules/inkycal_agenda.py @@ -14,7 +14,7 @@ import arrow filename = os.path.basename(__file__).split('.py')[0] logger = logging.getLogger(filename) -logger.setLevel(level=logging.ERROR) +logger.setLevel(level=logging.INFO) class Agenda(inkycal_module): """Agenda class @@ -33,7 +33,6 @@ class Agenda(inkycal_module): optional = { "ical_files" : { "label":"iCalendar filepaths, separated with a comma", - "default":[] }, "date_format":{ @@ -45,27 +44,37 @@ class Agenda(inkycal_module): "time_format":{ "label":"Use an arrow-supported token for custom time formatting "+ "see https://arrow.readthedocs.io/en/stable/#supported-tokens, e.g. HH:mm", + "default":"HH:mm", }, } - def __init__(self, section_size, section_config): + def __init__(self, config): """Initialize inkycal_agenda module""" - super().__init__(section_size, section_config) + super().__init__(config) - for param in self.equires: - if not param in section_config: + config = config['config'] + + # Check if all required parameters are present + for param in self.requires: + if not param in config: raise Exception('config is missing {}'.format(param)) # module specific parameters - self.date_format = self.config['date_format'] - self.time_format = self.config['time_format'] - self.language = self.config['language'] - self.ical_urls = self.config['ical_urls'] - self.ical_files = self.config['ical_files'] + self.date_format = config['date_format'] + self.time_format = config['time_format'] + self.language = config['language'] + self.ical_urls = config['ical_urls'].split(',') + # Check if ical_files is an empty string + if config['ical_files'] != "": + self.ical_files = config['ical_files'].split(',') + else: + self.ical_files = [] + + # Additional config self.timezone = get_system_tz() # give an OK message @@ -83,9 +92,6 @@ class Agenda(inkycal_module): if not isinstance(self.language, str): print('language has to be a string: "en" ') - if not isinstance(self.timezone, str): - print('The timezone has bo be a string.') - if not isinstance(self.ical_urls, list): print('ical_urls has to be a list ["url1", "url2"] ') @@ -96,8 +102,8 @@ class Agenda(inkycal_module): """Generate image for this module""" # Define new image size with respect to padding - im_width = int(self.width - (self.width * 2 * self.margin_x)) - im_height = int(self.height - (self.height * 2 * self.margin_y)) + im_width = int(self.width - (2 * self.padding_left)) + im_height = int(self.height - (2 * self.padding_top)) im_size = im_width, im_height logger.info('Image size: {0}'.format(im_size)) @@ -130,6 +136,7 @@ class Agenda(inkycal_module): if self.ical_urls: parser.load_url(self.ical_urls) + if self.ical_files: parser.load_from_file(self.ical_files) @@ -139,7 +146,7 @@ class Agenda(inkycal_module): # Sort events by beginning time parser.sort() - # parser.show_events() + #parser.show_events() # Set the width for date, time and event titles date_width = int(max([self.font.getsize( @@ -147,8 +154,13 @@ class Agenda(inkycal_module): for dates in agenda_events]) * 1.2) logger.debug(('date_width:', date_width)) + # Calculate positions for each line + line_pos = [(0, int(line * line_height)) for line in range(max_lines)] + logger.debug(('line_pos:', line_pos)) + # Check if any events were filtered if upcoming_events: + logger.info('Managed to parse events from urls') # Find out how much space the event times take time_width = int(max([self.font.getsize( @@ -168,10 +180,6 @@ class Agenda(inkycal_module): x_event = date_width + time_width logger.debug(('x-event:', x_event)) - # Calculate positions for each line - line_pos = [(0, int(line * line_height)) for line in range(max_lines)] - logger.debug(('line_pos:', line_pos)) - # Merge list of dates and list of events agenda_events += upcoming_events @@ -216,6 +224,8 @@ class Agenda(inkycal_module): # If no events were found, write only dates and lines else: + logger.info('no events found') + cursor = 0 for _ in agenda_events: title = _['title'] @@ -228,10 +238,9 @@ class Agenda(inkycal_module): cursor += 1 - logger.info('no events found') # return the images ready for the display return im_black, im_colour if __name__ == '__main__': - print('running {0} in standalone mode'.format(filename)) + print('running {0} in standalone mode'.format(filename)) \ No newline at end of file diff --git a/inkycal/modules/inkycal_calendar.py b/inkycal/modules/inkycal_calendar.py index 1722464..79637fa 100644 --- a/inkycal/modules/inkycal_calendar.py +++ b/inkycal/modules/inkycal_calendar.py @@ -12,7 +12,7 @@ import arrow filename = os.path.basename(__file__).split('.py')[0] logger = logging.getLogger(filename) -logger.setLevel(level=logging.ERROR) +logger.setLevel(level=logging.DEBUG) class Calendar(inkycal_module): """Calendar class @@ -37,12 +37,10 @@ class Calendar(inkycal_module): "ical_urls" : { "label":"iCalendar URL/s, separate multiple ones with a comma", - "default":[] }, "ical_files" : { "label":"iCalendar filepaths, separated with a comma", - "default":[] }, "date_format":{ @@ -59,24 +57,33 @@ class Calendar(inkycal_module): } - def __init__(self, section_size, section_config): + def __init__(self, config): """Initialize inkycal_calendar module""" - super().__init__(section_size, section_config) + super().__init__(config) + config = config['config'] + # optional parameters + self.weekstart = config['week_starts_on'] + self.show_events = bool(config['show_events']) + self.date_format = config["date_format"] + self.time_format = config['time_format'] + self.language = config['language'] - # module specific parameters + if config['ical_urls'] != "": + self.ical_urls = config['ical_urls'].split(',') + else: + self.ical_urls = [] + + if config['ical_files'] != "": + self.ical_files = config['ical_files'].split(',') + else: + self.ical_files = [] + + # additional configuration + self.timezone = get_system_tz() self.num_font = ImageFont.truetype( fonts['NotoSans-SemiCondensed'], size = self.fontsize) - self.weekstart = self.config['week_starts_on'] - self.show_events = self.config['show_events'] - self.date_format = self.config["date_format"] - self.time_format = self.config['time_format'] - self.language = self.config['language'] - - self.timezone = get_system_tz() - self.ical_urls = self.config['ical_urls'] - self.ical_files = self.config['ical_files'] # give an OK message print('{0} loaded'.format(filename)) @@ -85,8 +92,8 @@ class Calendar(inkycal_module): """Generate image for this module""" # Define new image size with respect to padding - im_width = int(self.width - (2 * self.padding_x)) - im_height = int(self.height - (2 * self.padding_y)) + im_width = int(self.width - (2 * self.padding_left)) + im_height = int(self.height - (2 * self.padding_top)) im_size = im_width, im_height logger.info('Image size: {0}'.format(im_size)) @@ -313,4 +320,4 @@ class Calendar(inkycal_module): return im_black, im_colour if __name__ == '__main__': - print('running {0} in standalone mode'.format(filename)) + print('running {0} in standalone mode'.format(filename)) \ No newline at end of file diff --git a/inkycal/modules/inkycal_rss.py b/inkycal/modules/inkycal_feeds.py similarity index 81% rename from inkycal/modules/inkycal_rss.py rename to inkycal/modules/inkycal_feeds.py index 90993c7..24143f1 100644 --- a/inkycal/modules/inkycal_rss.py +++ b/inkycal/modules/inkycal_feeds.py @@ -18,7 +18,7 @@ except ImportError: filename = os.path.basename(__file__).split('.py')[0] logger = logging.getLogger(filename) -logger.setLevel(level=logging.ERROR) +logger.setLevel(level=logging.INFO) class RSS(inkycal_module): """RSS class @@ -28,7 +28,7 @@ class RSS(inkycal_module): name = "Inkycal RSS / Atom" requires = { - "rss_urls" : { + "feed_urls" : { "label":"Please enter ATOM or RSS feed URL/s, separated by a comma", }, @@ -44,23 +44,24 @@ class RSS(inkycal_module): } - def __init__(self, section_size, section_config): - """Initialize inkycal_rss module""" + def __init__(self, config): + """Initialize inkycal_feeds module""" - super().__init__(section_size, section_config) + super().__init__(config) - # Check if required parameters are available in config + config = config['config'] + + # Check if all required parameters are present for param in self.requires: - if not param in section_config: + if not param in config: raise Exception('config is missing {}'.format(param)) - # parse required config - self.rss_urls = self.config["rss_urls"].split(",") + # required parameters + self.feed_urls = self.config["feed_urls"].split(",") - # parse optional config - self.shuffle_feeds = self.config["shuffle_feeds"] + # optional parameters + self.shuffle_feeds = bool(self.config["shuffle_feeds"]) - # give an OK message print('{0} loaded'.format(filename)) @@ -75,8 +76,8 @@ class RSS(inkycal_module): """Generate image for this module""" # Define new image size with respect to padding - im_width = int(self.width - ( 2 * self.padding_x)) - im_height = int(self.height - (2 * self.padding_y)) + im_width = int(self.width - (2 * self.padding_left)) + im_height = int(self.height - (2 * self.padding_top)) im_size = im_width, im_height logger.info('image size: {} x {} px'.format(im_width, im_height)) @@ -90,7 +91,7 @@ class RSS(inkycal_module): else: raise Exception('Network could not be reached :/') - # Set some parameters for formatting rss feeds + # Set some parameters for formatting feeds line_spacing = 1 line_height = self.font.getsize('hg')[1] + line_spacing line_width = im_width @@ -103,9 +104,9 @@ class RSS(inkycal_module): line_positions = [ (0, spacing_top + _ * line_height ) for _ in range(max_lines)] - # Create list containing all rss-feeds from all rss-feed urls + # Create list containing all feeds from all urls parsed_feeds = [] - for feeds in self.rss_urls: + for feeds in self.feed_urls: text = feedparser.parse(feeds) for posts in text.entries: parsed_feeds.append('•{0}: {1}'.format(posts.title, posts.summary)) @@ -131,23 +132,21 @@ class RSS(inkycal_module): filtered_feeds = flatten(filtered_feeds) self._filtered_feeds = filtered_feeds + logger.debug(f'filtered feeds -> {filtered_feeds}') + # Check if feeds could be parsed and can be displayed if len(filtered_feeds) == 0 and len(parsed_feeds) > 0: print('Feeds could be parsed, but the text is too long to be displayed:/') elif len(filtered_feeds) == 0 and len(parsed_feeds) == 0: print('No feeds could be parsed :/') else: - # Write rss-feeds on image + # Write feeds on image for _ in range(len(filtered_feeds)): write(im_black, line_positions[_], (line_width, line_height), filtered_feeds[_], font = self.font, alignment= 'left') - # Cleanup - del filtered_feeds, parsed_feeds, wrapped, counter, text - # Save image of black and colour channel in image-folder return im_black, im_colour if __name__ == '__main__': - print('running {0} in standalone/debug mode'.format(filename)) - print(RSS.get_config()) + print('running {0} in standalone/debug mode'.format(filename)) \ No newline at end of file diff --git a/inkycal/modules/inkycal_todoist.py b/inkycal/modules/inkycal_todoist.py index aabb348..416808b 100644 --- a/inkycal/modules/inkycal_todoist.py +++ b/inkycal/modules/inkycal_todoist.py @@ -169,8 +169,4 @@ class Todoist(inkycal_module): return im_black, im_colour if __name__ == '__main__': - print('running {0} in standalone/debug mode'.format(filename)) - config = {'api_key':'4e166367dcafdd60e6a9f4cbed598d578bf2c359'} - size = (480, 100) - a = Todoist(size, config) - b,c = a.generate_image() + print('running {0} in standalone/debug mode'.format(filename)) \ No newline at end of file diff --git a/inkycal/modules/inkycal_weather.py b/inkycal/modules/inkycal_weather.py index e5b1300..596a5e4 100644 --- a/inkycal/modules/inkycal_weather.py +++ b/inkycal/modules/inkycal_weather.py @@ -81,42 +81,74 @@ class Weather(inkycal_module): } - def __init__(self, section_size, section_config): + def __init__(self, config): """Initialize inkycal_weather module""" - super().__init__(section_size, section_config) + super().__init__(config) - # Module specific parameters + config = config['config'] + + # Check if all required parameters are present for param in self.requires: - if not param in section_config: + if not param in config: raise Exception('config is missing {}'.format(param)) # required parameters - self.location = self.config['location'] - self.api_key = self.config['api_key'] + self.location = config['location'] + self.api_key = config['api_key'] # optional parameters - self.round_temperature = self.config['round_temperature'] - self.round_windspeed = self.config['round_windspeed'] - self.forecast_interval = self.config['forecast_interval'] - self.units = self.config['units'] - self.hour_format = self.config['hour_format'] - self.use_beaufort = self.config['use_beaufort'] + self.round_temperature = bool(config['round_temperature']) + self.round_windspeed = bool(config['round_windspeed']) + self.forecast_interval = config['forecast_interval'] + self.units = config['units'] + self.hour_format = int(config['hour_format']) + self.use_beaufort = bool(config['use_beaufort']) + + # additional configuration + self.owm = pyowm.OWM(self.api_key) self.timezone = get_system_tz() self.locale = sys_locale()[0] - self.weatherfont = ImageFont.truetype(fonts['weathericons-regular-webfont'], - size = self.fontsize) + self.weatherfont = ImageFont.truetype( + fonts['weathericons-regular-webfont'], size = self.fontsize) - #self.owm = pyowm.OWM(self.config['api_key']) # give an OK message print('{0} loaded'.format(filename)) + + def _validate(self): + + if not isinstance(self.location, str): + print(f'location should be -> Manchester, USA, not {self.location}') + + if not isinstance(self.api_key, str): + print(f'api_key should be a string, not {self.api_key}') + + if not isinstance(self.round_temperature, bool): + print(f'round_temperature should be a boolean, not {self.round_temperature}') + + if not isinstance(self.round_windspeed, bool): + print(f'round_windspeed should be a boolean, not {self.round_windspeed}') + + if not isinstance(self.forecast_interval, int): + print(f'forecast_interval should be a boolean, not {self.forecast_interval}') + + if not isinstance(self.units, str): + print(f'units should be a boolean, not {self.units}') + + if not isinstance(self.hour_format, int): + print(f'hour_format should be a int, not {self.hour_format}') + + if not isinstance(self.use_beaufort, bool): + print(f'use_beaufort should be a int, not {self.use_beaufort}') + + def generate_image(self): """Generate image for this module""" # Define new image size with respect to padding - im_width = int(self.width - (2 * self.padding_x)) - im_height = int(self.height - (2 * self.padding_y)) + im_width = int(self.width - (2 * self.padding_left)) + im_height = int(self.height - (2 * self.padding_top)) im_size = im_width, im_height logger.info('image size: {} x {} px'.format(im_width, im_height)) @@ -338,6 +370,10 @@ class Weather(inkycal_module): elif self.forecast_interval == 'daily': + ### + logger.debug("daily") + + def calculate_forecast(days_from_today): """Get temperature range and most frequent icon code for forecast days_from_today should be int from 1-4: e.g. 2 -> 2 days from today @@ -352,7 +388,6 @@ class Weather(inkycal_module): # Get forecasts for each time-object forecasts = [forecast.get_weather_at(_.datetime) for _ in time_range] - # Get all temperatures for this day daily_temp = [round(_.get_temperature(unit=temp_unit)['temp'], ndigits=dec_temp) for _ in forecasts] @@ -418,7 +453,6 @@ class Weather(inkycal_module): moonphase = get_moon_phase() # Fill weather details in col 1 (current weather icon) - # write(im_black, (col_width, row_height), now_str, text_now_pos, font = font) draw_icon(im_colour, weather_icon_pos, (icon_large, icon_large), weathericons[weather_icon]) @@ -481,4 +515,4 @@ class Weather(inkycal_module): return im_black, im_colour if __name__ == '__main__': - print('running {0} in standalone mode'.format(filename)) + print('running {0} in standalone mode'.format(filename)) \ No newline at end of file diff --git a/inkycal/modules/template.py b/inkycal/modules/template.py index 606673c..e08ee27 100644 --- a/inkycal/modules/template.py +++ b/inkycal/modules/template.py @@ -1,6 +1,10 @@ import abc from inkycal.custom import * +# Set the root logger to level DEBUG to allow any inkycal module to use the +# logger for any level +logging.basicConfig(level = logging.DEBUG) + class inkycal_module(metaclass=abc.ABCMeta): """Generic base class for inykcal modules""" @@ -10,16 +14,18 @@ class inkycal_module(metaclass=abc.ABCMeta): callable(subclass.generate_image) or NotImplemented) - def __init__(self, section_config): + def __init__(self, config): + """Initialize module with given config""" + # Initializes base module # sets properties shared amongst all sections - self.config = section_config - self.width, self.height = section_config['size'] + self.config = conf = config['config'] + self.width, self.height = conf['size'] - self.padding_left = self.padding_right = self.config["padding_x"] - self.padding_top = self.padding_bottom = self.config["padding_y"] + self.padding_left = self.padding_right = conf["padding_x"] + self.padding_top = self.padding_bottom = conf['padding_y'] - self.fontsize = self.config["fontsize"] + self.fontsize = conf["fontsize"] self.font = ImageFont.truetype( fonts['NotoSans-SemiCondensed'], size = self.fontsize) diff --git a/inkycal/modules/test_module.py b/inkycal/modules/test_module.py index d8877be..c79b41f 100644 --- a/inkycal/modules/test_module.py +++ b/inkycal/modules/test_module.py @@ -1,9 +1,7 @@ #!/usr/bin/python3 # -*- coding: utf-8 -*- """ -Module template for Inky-Calendar Project - -Create your own module with this template +Developer module template for Inkycal Project Copyright by aceisace """ @@ -79,9 +77,6 @@ class Simple(inkycal_module): # Initialise this module via the inkycal_module template (required) super().__init__(section_size, section_config) - # module name (required) - self.name = self.__class__.__name__ - # module specific parameters (optional) self.do_something = True