add some nice-to-have features, e.g. battery capacity checking of PiSugar

This commit is contained in:
Ace 2024-06-25 13:17:00 +02:00
parent 92ef847618
commit fdd5591456
3 changed files with 49 additions and 16 deletions

View File

@ -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()
@ -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')

View File

@ -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

View File

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