""" uv-belichter-software - the SETTINGS submenu Copyright (C) 2024 Benjamin Burkhardt This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ from time import sleep, time_ns # All the arguments this method takes are there for one reason: reduce the amount of libraries loaded into the picos memory and thus improving performance # config: utils.Config object # btn_mapping: a dict containing the btn mapping for the menu operation (given to the lcdMenu object) # log: the utils.log function # lcdMenu: the lcdMenu class (not an object of that class!) def run(config, btn_mapping, log, lcdMenu): settings_menu = lcdMenu(config.LCD, btn_mapping, scroll_direction=True, cycle=True, hide_menu_name=False, name="SETTINGS") def toggle_show_welcome(): current_value = config.STARTUP_WELCOME_SHOW config.LCD.clear() config.LCD.putstr(f"Currently {'on' if current_value else 'off'}".center(16)) config.LCD.putstr("< keep change >") keep_btn = config.PIN_IN_BTN_1 change_btn = config.PIN_IN_BTN_2 while True: if keep_btn.value() == 1: config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Stay {'on' if current_value else 'off'}!".center(16)) sleep(0.5) return True if change_btn.value() == 1: config.STARTUP_WELCOME_SHOW = not current_value config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Turned {'on' if not current_value else 'off'}!".center(16)) sleep(0.5) return True def welcome_cycles(): config.LCD.clear() current_cycles = config.STARTUP_WELCOME_CYCLES option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") btn_left = config.PIN_IN_BTN_1 btn_right = config.PIN_IN_BTN_2 while True: if btn_left.value() == 1: sleep(0.1) # this value is a good compromise between being able to press both buttons and a fast up/down speed if btn_right.value() == 1: config.STARTUP_WELCOME_CYCLES = current_cycles config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True current_cycles -= 1 if current_cycles < 1: current_cycles = 1 option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") if btn_right.value() == 1: sleep(0.1) if btn_left.value() == 1: config.STARTUP_WELCOME_CYCLES = current_cycles config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True current_cycles += 1 option_down = [" ", "v"][current_cycles>1] config.LCD.putstr(f" Cycles \n{option_down} {str(current_cycles).center(12)} ^") # with n being the number of the timer (starting at 0) def set_n_timer(n: int): # a small helper function to save the value of the n'th timer... # as you can't programatically access TIMER_n_DURATION def set_timer_helper(n, value): if n == 0: config.TIMER_1_DURATION = value elif n == 1: config.TIMER_2_DURATION = value elif n == 2: config.TIMER_3_DURATION = value else: log(0, "There are only 3 timers at all. Trying to set the timer number {n} failed.") config.LCD.clear() timer_values = [config.TIMER_1_DURATION, config.TIMER_2_DURATION, config.TIMER_3_DURATION] current_timer = timer_values[n] # get the n'th timer current_timer_div = lambda: divmod(current_timer, 60) config.LCD.putstr(f"Timer {n+1}".center(16)) config.LCD.putstr(f"{'v' if current_timer > 1 else ' '} " + f"{current_timer_div()[0]:02d}:{current_timer_div()[1]:02d}".center(12) + " ^") btn_left = config.PIN_IN_BTN_1 btn_right = config.PIN_IN_BTN_2 left_was_released = True right_was_released = True while True: if btn_left.value() == 1: if left_was_released: time_press_start = time_ns() left_was_released = False sleep(0.1) # this value is a good compromise between being able to press both buttons and a fast up/down speed if btn_right.value() == 1: # exit if both btns are pressed set_timer_helper(n, current_timer) config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True # define the step width time_now = time_ns() if (time_now - time_press_start) <= 1*(10**9): # max. 1 seconds pressed current_timer -= 1 elif (time_now - time_press_start) <= 2*(10**9): # max. 2 seconds pressed current_timer -= 5 elif (time_now - time_press_start) <= 3*(10**9): # max. 3 seconds pressed current_timer -= 10 elif (time_now - time_press_start) <= 4*(10**9): # max. 4 seconds pressed current_timer -= 30 elif (time_now - time_press_start) <= 5*(10**9): # max. 5 seconds pressed current_timer -= 60 else: # longer than 5s pressed current_timer -= 300 if current_timer < 1: current_timer = 5999 config.LCD.move_to(0,1) config.LCD.putstr("v " + f"{current_timer_div()[0]:02d}:{current_timer_div()[1]:02d}".center(12) + " ^") else: left_was_released = True if btn_right.value() == 1: if right_was_released: time_press_start = time_ns() right_was_released = False sleep(0.1) if btn_left.value() == 1: # exit if both btns are pressed set_timer_helper(n, current_timer) config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True # define the step width time_now = time_ns() if (time_now - time_press_start) <= 1*(10**9): # max. 1 seconds pressed current_timer += 1 elif (time_now - time_press_start) <= 2*(10**9): # max. 2 seconds pressed current_timer += 5 elif (time_now - time_press_start) <= 3*(10**9): # max. 3 seconds pressed current_timer += 10 elif (time_now - time_press_start) <= 4*(10**9): # max. 4 seconds pressed current_timer += 30 elif (time_now - time_press_start) <= 5*(10**9): # max. 5 seconds pressed current_timer += 60 else: # longer than 5s pressed current_timer += 300 if current_timer > 5999: current_timer = 1 config.LCD.move_to(0,1) config.LCD.putstr("v " + f"{current_timer_div()[0]:02d}:{current_timer_div()[1]:02d}".center(12) + " ^") else: right_was_released = True def set_log_level(): config.LCD.clear() current_level = config.LOG_LEVEL log_levels = ["WARN", "INFO", "DEBUG"] config.LCD.putstr(f"Log level".center(16)) config.LCD.putstr("v " + f"{log_levels[current_level]} ({current_level})".center(12) + " ^") # show the log level and it's name in the second row btn_left = config.PIN_IN_BTN_1 btn_right = config.PIN_IN_BTN_2 while True: if btn_left.value() == 1: sleep(0.1) # this value is a good compromise between being able to press both buttons and a fast up/down speed if btn_right.value() == 1: config.LOG_LEVEL = current_level config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True current_level -= 1 if current_level < 0: current_level = 2 config.LCD.move_to(0,0) config.LCD.putstr(f"Log level".center(16)) config.LCD.putstr("v " + f"{log_levels[current_level]} ({current_level})".center(12) + " ^") # show the log level and it's name in the second row if btn_right.value() == 1: sleep(0.1) if btn_left.value() == 1: config.LOG_LEVEL = current_level config.LCD.move_to(0,1) # move to the second row config.LCD.putstr(f"Saved!".center(16)) # show a little info that it is now set sleep(0.5) while btn_right.value() == 1 or btn_left.value() == 1: # wait till both btns are released pass return True current_level += 1 if current_level > 2: current_level = 0 config.LCD.move_to(0,0) config.LCD.putstr(f"Log level".center(16)) config.LCD.putstr("v " + f"{log_levels[current_level]} ({current_level})".center(12) + " ^") # show the log level and it's name in the second row def reset(): # reset all user-settable configuration to the default values config.LCD.clear() config.LCD.putstr("Sure about that?") config.LCD.putstr("< no yes >") no_btn = config.PIN_IN_BTN_1 yes_btn = config.PIN_IN_BTN_2 while True: if no_btn.value() == 1: return None if yes_btn.value() == 1: config.LCD.putstr("Resetting...".center(16)) config.LCD.putstr("Welcome Screen".center(16)) config.STARTUP_WELCOME_SHOW = True config.STARTUP_WELCOME_CYCLES = 1 sleep(0.5) config.LCD.move_to(0,1) config.LCD.putstr("Timers".center(16)) config.TIMER_1_DURATION = 60 config.TIMER_2_DURATION = 2400 config.TIMER_3_DURATION = 2700 sleep(0.5) config.LCD.move_to(0,1) config.LCD.putstr("Logging".center(16)) config.LOG_LEVEL = 1 sleep(0.5) return True settings_programs = [("Show welcome", toggle_show_welcome), ("Welcome cycles", welcome_cycles), ("Timer 1", lambda: set_n_timer(0)), ("Timer 2", lambda: set_n_timer(1)), ("Timer 3", lambda: set_n_timer(2)), ("Log level", set_log_level), ("Reset", reset), ("Exit", settings_menu.stop)] settings_menu.setup(settings_programs) # give it the callback list settings_menu.run() # run the menu until it's closed if __name__ == "__main__": from utils import Config, log from lcdMenu import lcdMenu config = Config() btn_mapping = {"ok_btn": config.PIN_IN_BTN_1, "next_btn": config.PIN_IN_BTN_2} # the btn mapping for all lcdMenus run(Config(), btn_mapping, log, lcdMenu)