It is now possible to use one, two or three modules and use the height defined by the settings file
		
			
				
	
	
		
			190 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/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'
 | |
|   ]
 | |
| 
 | |
|   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)
 | |
|       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
 | |
|     self.Layout = Layout(model=self.model)
 | |
|     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']
 | |
| 
 | |
|     # 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']
 | |
|     self.update_interval = settings['update_interval']
 | |
|     self.calibration_hours = settings['calibration_hours']
 | |
|     self.display_orientation = settings['display_orientation']
 | |
| 
 | |
|     # 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'
 | |
| 
 | |
|     print('Settings file OK!')
 | |
| 
 | |
|   def active_modules(self):
 | |
|     modules = [section['type'] for section in self._settings['panels']]
 | |
|     return modules
 | |
| 
 | |
|   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}
 | |
| 
 | |
|   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]))
 | |
| 
 |