add some nice-to-have features, e.g. battery capacity checking of PiSugar
This commit is contained in:
parent
92ef847618
commit
fdd5591456
@ -37,15 +37,19 @@ class Inkycal:
|
|||||||
to improve rendering on E-Papers. Set this to False for 9.7" E-Paper.
|
to improve rendering on E-Papers. Set this to False for 9.7" E-Paper.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, settings_path: str or None = None, render: bool = True):
|
def __init__(self, settings_path: str or None = None, render: bool = True, use_pi_sugar: bool = False):
|
||||||
"""Initialise Inkycal"""
|
"""Initialise Inkycal"""
|
||||||
self._release = "2.0.3"
|
self._release = "2.0.3"
|
||||||
|
|
||||||
|
logger.info(f"Inkycal v{self._release} booting up...")
|
||||||
|
|
||||||
self.render = render
|
self.render = render
|
||||||
self.info = None
|
self.info = None
|
||||||
|
|
||||||
|
logger.info("Checking if a settings file is present...")
|
||||||
# load settings file - throw an error if file could not be found
|
# load settings file - throw an error if file could not be found
|
||||||
if settings_path:
|
if settings_path:
|
||||||
|
logger.info(f"Custom location for settings.json file specified: {settings_path}")
|
||||||
try:
|
try:
|
||||||
with open(settings_path) as settings_file:
|
with open(settings_path) as settings_file:
|
||||||
self.settings = json.load(settings_file)
|
self.settings = json.load(settings_file)
|
||||||
@ -55,6 +59,7 @@ class Inkycal:
|
|||||||
f"No settings.json file could be found in the specified location: {settings_path}")
|
f"No settings.json file could be found in the specified location: {settings_path}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
logger.info("Looking for settings.json file in /boot folder...")
|
||||||
try:
|
try:
|
||||||
with open('/boot/settings.json', mode="r") as settings_file:
|
with open('/boot/settings.json', mode="r") as settings_file:
|
||||||
self.settings = json.load(settings_file)
|
self.settings = json.load(settings_file)
|
||||||
@ -63,6 +68,8 @@ class Inkycal:
|
|||||||
raise SettingsFileNotFoundError
|
raise SettingsFileNotFoundError
|
||||||
|
|
||||||
self.disable_calibration = self.settings.get('disable_calibration', False)
|
self.disable_calibration = self.settings.get('disable_calibration', False)
|
||||||
|
if self.disable_calibration:
|
||||||
|
logger.info("Calibration disabled. Please proceed with caution to prevent ghosting.")
|
||||||
|
|
||||||
if not os.path.exists(settings.IMAGE_FOLDER):
|
if not os.path.exists(settings.IMAGE_FOLDER):
|
||||||
os.mkdir(settings.IMAGE_FOLDER)
|
os.mkdir(settings.IMAGE_FOLDER)
|
||||||
@ -132,16 +139,31 @@ class Inkycal:
|
|||||||
|
|
||||||
self.counter = 0 if "counter" not in self.cache_data else int(self.cache_data["counter"])
|
self.counter = 0 if "counter" not in self.cache_data else int(self.cache_data["counter"])
|
||||||
|
|
||||||
self.use_pi_sugar = True
|
self.use_pi_sugar = use_pi_sugar
|
||||||
print("Please remove hardcoded value of pisugar!")
|
self.battery_capacity = 100
|
||||||
|
|
||||||
if self.use_pi_sugar:
|
if self.use_pi_sugar:
|
||||||
|
logger.info("PiSugar support enabled.")
|
||||||
from inkycal.utils import PiSugar
|
from inkycal.utils import PiSugar
|
||||||
self.pisugar = PiSugar()
|
self.pisugar = PiSugar()
|
||||||
print(f"Using PiSigar model: {self.pisugar.get_model()}. Current PiSugar time: {self.pisugar.get_rtc_time()}")
|
|
||||||
|
self.battery_capacity = self.pisugar.get_battery()
|
||||||
|
logger.info(f"PiSugar battery capacity: {self.battery_capacity}%")
|
||||||
|
|
||||||
|
if self.battery_capacity < 20:
|
||||||
|
logger.warning("Battery capacity is below 20%!")
|
||||||
|
|
||||||
|
logger.info("Setting system time to PiSugar time...")
|
||||||
|
if self.pisugar.rtc_pi2rtc():
|
||||||
|
logger.info("RTC time updates successfully")
|
||||||
|
else:
|
||||||
|
logger.warning("RTC time could not be set!")
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"Using PiSigar model: {self.pisugar.get_model()}. Current PiSugar time: {self.pisugar.get_rtc_time()}")
|
||||||
|
|
||||||
# Give an OK message
|
# Give an OK message
|
||||||
print('loaded inkycal')
|
logger.info('Inkycal initialised successfully!')
|
||||||
|
|
||||||
def countdown(self, interval_mins: int = None) -> int:
|
def countdown(self, interval_mins: int = None) -> int:
|
||||||
"""Returns the remaining time in seconds until the next display update based on the interval.
|
"""Returns the remaining time in seconds until the next display update based on the interval.
|
||||||
@ -179,7 +201,7 @@ class Inkycal:
|
|||||||
|
|
||||||
return seconds_to_next_interval
|
return seconds_to_next_interval
|
||||||
|
|
||||||
def test(self):
|
def dry_run(self):
|
||||||
"""Tests if Inkycal can run without issues.
|
"""Tests if Inkycal can run without issues.
|
||||||
|
|
||||||
Attempts to import module names from settings file. Loads the config
|
Attempts to import module names from settings file. Loads the config
|
||||||
@ -269,7 +291,6 @@ class Inkycal:
|
|||||||
# Function to flip images upside down
|
# Function to flip images upside down
|
||||||
upside_down = lambda image: image.rotate(180, expand=True)
|
upside_down = lambda image: image.rotate(180, expand=True)
|
||||||
|
|
||||||
|
|
||||||
print(f'Inkycal version: v{self._release}')
|
print(f'Inkycal version: v{self._release}')
|
||||||
print(f'Selected E-paper display: {self.settings["model"]}')
|
print(f'Selected E-paper display: {self.settings["model"]}')
|
||||||
|
|
||||||
@ -291,7 +312,7 @@ class Inkycal:
|
|||||||
success = self.process_module(number)
|
success = self.process_module(number)
|
||||||
if not success:
|
if not success:
|
||||||
errors.append(number)
|
errors.append(number)
|
||||||
self.info += f"module {number}: Error! "
|
self.info += f"im {number}: X "
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
logger.error("Error/s in modules:", *errors)
|
logger.error("Error/s in modules:", *errors)
|
||||||
@ -301,6 +322,9 @@ class Inkycal:
|
|||||||
logger.info("successful")
|
logger.info("successful")
|
||||||
del errors
|
del errors
|
||||||
|
|
||||||
|
if self.battery_capacity < 20:
|
||||||
|
self.info += "Low battery! "
|
||||||
|
|
||||||
# Assemble image from each module - add info section if specified
|
# Assemble image from each module - add info section if specified
|
||||||
self._assemble()
|
self._assemble()
|
||||||
|
|
||||||
@ -337,7 +361,7 @@ class Inkycal:
|
|||||||
im_black = upside_down(im_black)
|
im_black = upside_down(im_black)
|
||||||
|
|
||||||
if not self.settings.get('image_hash', False) or self._needs_image_update([
|
if not self.settings.get('image_hash', False) or self._needs_image_update([
|
||||||
(f"{self.image_folder}/canvas.png.hash", im_black),]):
|
(f"{self.image_folder}/canvas.png.hash", im_black), ]):
|
||||||
display.render(im_black)
|
display.render(im_black)
|
||||||
|
|
||||||
print(f'\nNo errors since {self.counter} display updates \n'
|
print(f'\nNo errors since {self.counter} display updates \n'
|
||||||
@ -353,13 +377,12 @@ class Inkycal:
|
|||||||
sleep_time = self.countdown()
|
sleep_time = self.countdown()
|
||||||
|
|
||||||
if self.use_pi_sugar:
|
if self.use_pi_sugar:
|
||||||
# todo make this timezone aware!
|
|
||||||
sleep_time_rtc = arrow.now(tz=get_system_tz()).shift(seconds=sleep_time)
|
sleep_time_rtc = arrow.now(tz=get_system_tz()).shift(seconds=sleep_time)
|
||||||
result = self.pisugar.rtc_alarm_set(sleep_time_rtc, 127)
|
result = self.pisugar.rtc_alarm_set(sleep_time_rtc, 127)
|
||||||
if result:
|
if result:
|
||||||
print(f"Alarm set for {sleep_time_rtc.format('HH:mm:ss')}")
|
logger.info(f"Alarm set for {sleep_time_rtc.format('HH:mm:ss')}")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to set alarm for {sleep_time_rtc.format('HH:mm:ss')}")
|
logger.warning(f"Failed to set alarm for {sleep_time_rtc.format('HH:mm:ss')}")
|
||||||
|
|
||||||
await asyncio.sleep(sleep_time)
|
await asyncio.sleep(sleep_time)
|
||||||
|
|
||||||
@ -575,6 +598,17 @@ class Inkycal:
|
|||||||
logger.exception(f"Error in module {number}!")
|
logger.exception(f"Error in module {number}!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _shutdown_system(self):
|
||||||
|
"""Shutdown the system"""
|
||||||
|
import subprocess
|
||||||
|
from time import sleep
|
||||||
|
try:
|
||||||
|
logger.info("Shutting down OS in 5 seconds...")
|
||||||
|
sleep(5)
|
||||||
|
subprocess.run(["sudo", "shutdown", "-h", "now"], check=True)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
logger.warning("Failed to execute shutdown command.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print(f'running inkycal main in standalone/debug mode')
|
print(f'running inkycal main in standalone/debug mode')
|
||||||
|
@ -121,8 +121,7 @@ class PiSugar:
|
|||||||
"""
|
"""
|
||||||
result = self._get_output("rtc_pi2rtc")
|
result = self._get_output("rtc_pi2rtc")
|
||||||
if result:
|
if result:
|
||||||
second_line = result.splitlines()[1]
|
status = result.split('rtc_pi2rtc: ')[1].strip()
|
||||||
status = second_line.split('rtc_pi2rtc: ')[1].strip()
|
|
||||||
if status == "done":
|
if status == "done":
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -21,9 +21,9 @@ class TestMain(unittest.TestCase):
|
|||||||
assert inkycal.settings["info_section_height"] == 70
|
assert inkycal.settings["info_section_height"] == 70
|
||||||
assert inkycal.settings["border_around_modules"] is True
|
assert inkycal.settings["border_around_modules"] is True
|
||||||
|
|
||||||
def test_run(self):
|
def test_dry_run(self):
|
||||||
inkycal = Inkycal(self.settings_path, render=False)
|
inkycal = Inkycal(self.settings_path, render=False)
|
||||||
inkycal.test()
|
inkycal.dry_run()
|
||||||
|
|
||||||
def test_countdown(self):
|
def test_countdown(self):
|
||||||
inkycal = Inkycal(self.settings_path, render=False)
|
inkycal = Inkycal(self.settings_path, render=False)
|
||||||
|
Loading…
Reference in New Issue
Block a user