| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | #!/usr/bin/python3 | 
					
						
							|  |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  | Json settings parser for inkycal project | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | Copyright by aceisace | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  | from inkycal.config.layout import Layout | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | import json | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  | logger = logging.getLogger('settings') | 
					
						
							|  |  |  | logger.setLevel(level=logging.DEBUG) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Settings: | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |   """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] | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  |   _supported_update_interval = [10, 15, 20, 30, 60] | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |   _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' | 
					
						
							|  |  |  |   ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def __init__(self, settings_file_path): | 
					
						
							|  |  |  |     """Load settings from path (folder or settings.json file)""" | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |       if settings_file_path.endswith('settings.json'): | 
					
						
							|  |  |  |         folder = settings_file_path.split('/settings.json')[0] | 
					
						
							|  |  |  |       else: | 
					
						
							|  |  |  |         folder = settings_file_path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       os.chdir(folder) | 
					
						
							|  |  |  |       with open("settings.json") as file: | 
					
						
							|  |  |  |         settings = json.load(file) | 
					
						
							|  |  |  |         self._settings = settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     except FileNotFoundError: | 
					
						
							|  |  |  |       print('No settings file found in specified location') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     # Validate the settings | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |     self._validate() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     # Get the height-percentages of the modules | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  |     self.Layout = Layout(model=self.model) | 
					
						
							|  |  |  |     all_heights = [_['height'] for _ in self._settings['panels']] | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     # If no height is provided, use default values | 
					
						
							|  |  |  |     if len(set(all_heights)) == 1 and None in all_heights: | 
					
						
							|  |  |  |       self.Layout.create_sections() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # if all heights are spcified, use given values | 
					
						
							|  |  |  |     elif len(set(all_heights)) != 1 and not None in all_heights: | 
					
						
							|  |  |  |       logger.info('Setting section height according to settings file') | 
					
						
							|  |  |  |       heights = [_['height']/100 for _ in self._settings['panels']] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       self.Layout.create_sections(top_section= heights[0], | 
					
						
							|  |  |  |                                   middle_section=heights[1], | 
					
						
							|  |  |  |                                   bottom_section=heights[2]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # 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!') | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |   def _validate(self): | 
					
						
							|  |  |  |     """Validate the basic config""" | 
					
						
							|  |  |  |     settings = self._settings | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     required =  ['language', 'units', 'hours', 'model', 'calibration_hours'] | 
					
						
							|  |  |  |             #'display_orientation'] | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Check if all required settings exist | 
					
						
							|  |  |  |     for param in required: | 
					
						
							|  |  |  |       if not param in settings: | 
					
						
							|  |  |  |         raise Exception ( | 
					
						
							|  |  |  |           'required parameter: {} 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'] | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  |     self.update_interval = settings['update_interval'] | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |     self.calibration_hours = settings['calibration_hours'] | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     #self.display_orientation = settings['display_orientation'] | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # 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' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |     if (not isinstance(self.calibration_hours, list)): | 
					
						
							|  |  |  |       print('calibration_hours not supported, switching to fallback, [0,12,18]') | 
					
						
							|  |  |  |       self.calibration_hours = [0,12,18] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  | ##    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' | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     print('Settings file OK!') | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |   def active_modules(self): | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |     modules = [section['type'] for section in self._settings['panels']] | 
					
						
							|  |  |  |     return modules | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def get_config(self, module_name): | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     """Ge the config of this module (size, config)""" | 
					
						
							|  |  |  |     if module_name not in self.active_modules(): | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |       print('No config is available for this module') | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |       for section in self._settings['panels']: | 
					
						
							|  |  |  |         if section['type'] == module_name: | 
					
						
							|  |  |  |           config = section['config'] | 
					
						
							| 
									
										
										
										
											2020-05-26 19:18:20 +02:00
										 |  |  |           size = self.Layout.get_size(self.get_position(module_name)) | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     return {'size':size, 'config':config} | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def get_position(self, module_name): | 
					
						
							|  |  |  |     """Get the position of this module's image on the display""" | 
					
						
							| 
									
										
										
										
											2020-05-23 01:45:40 +02:00
										 |  |  |     if module_name not in self.active_modules(): | 
					
						
							| 
									
										
										
										
											2020-05-21 19:52:39 +02:00
										 |  |  |       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])) | 
					
						
							|  |  |  | 
 |