Inkycal/inkycal/config/settings_parser.py
Ace f8834c4c21 Improved layout setup
It is now possible to use one, two or three modules and use the height defined by the settings file
2020-06-13 16:14:49 +02:00

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]))