class KPC: """main method including variables""" def __init__(self): """Initialiser, setting the initializer""" self.keypad = Keypad() self.LED = LED_board() self.passcode_buffer = '' self.digit = '' self.path_password = '******' self.override_signal = '' self.LED_id = '' self.LED_duration = '' self.new_pass = '' self.new_pass_check = '' f = open(self.path_password) try: self.password = f.read().strip() except IOError: print("Could not set password") finally: f.close() def init_passcode_entry(self): """clear passcode buffer and initiate a power up lighting sequence""" self.passcode_buffer = '' self.LED.led_power_up() def get_next_signal(self): """return the override-signal, if its non-blank. else query keypad for next pressed key""" if self.override_signal != '': return self.override_signal self.digit = self.keypad.get_next_signal() return self.digit def append_password_buffer(self): """Appends password with newly pressed digit""" self.password_buffer += self.digit def append_new_pass(self): """Appends password with newly pressed digit""" self.new_pass += self.digit self.digit = '' def append_new_pass_check(self): """Appends password with newly pressed digit""" self.new_pass_check += self.digit self.digit = '' def append_Ldur(self): """Appends digit to time-variable""" self.LED_duration += self.digit def set_led(self): """Sets the Lpin""" self.LED_id = self.digit def verify_login(self): """Checks the password. store as Y or N(Yes or No) in the override-signal. call LED board for fail or pass lighting""" if self.passcode_buffer == self.password: self.override_signal = 'Y' self.LED.led_login_successful() print('correct password') else: self.override_signal = 'N' self.password_buffer = '' def validate_passcode_change(self): # ikke fullført """check if new password is legal. if so write to password file. Password: 4 digits or more, only digits 0-9. call LED board for fail or pass lighting """ # Tre rød LEDs for fail og tre grønne for pass? if self.new_pass == self.new_pass_check: self.password = self.new_pass self.LED.led_pass_change_successful() else: self.LED.led_pass_change_unsuccessful() self.new_pass = '' self.new_pass_check = '' def set_password(self): """stores new password in password file""" # må vi slette passordet på begynnelsen? with open(self.path_password, 'w') as file: file.write(self.password) def light_one_led(self): # trenger vi denne????? """Using values stored in the Lid and Ldur slots, call the LED Board and request that LED # Lid be turned on for Ldur seconds """ self.LED.light_single_led( int(self.LED_id), self.LED_duration) # Usikker på om LED_id må castes til int def flash_led(self): """call LED board and request flashing og LEDs""" self.LED.flash_all_leds() def twinkle_led(self): """call LED board and request twinkling og LEDs""" self.LED.twinkle_all_leds(self.LED_duration) def reset_all_variables(self): self.passcode_buffer = '' self.override_signal = None self.new_pass = '' self.new_pass_check = '' self.LED_id = '' self.LED_duration = '' def power_down(self): # hanna skjønner ikke helt denne her """Close file and call LED board to initiate power down LEDs""" # Lagrer passord i filen når keypad-en slås av f = open(self.path_password, "w") try: self.password except IOError: print("Couldn't save password in respective file") finally: f.close() self.LED.led_power_down() def nothing(self): pass
class KpcAgent: """Keypad Controller Agent Class""" def __init__(self) -> None: self.keypad = Keypad() self.leds = LedDriver() self.override_signal = None self.entry_buffer = "" self.passcode = None def light_led(self, duration): """Light led from buffer""" led = int(self.entry_buffer) duration = int(duration) if 6 > led >= 0: self.light_one_led(led, duration) self.reset_buffer() def power_down(self): """Power down""" self.reset_buffer() self.leds.power_down() def wakeup(self): """Power up system""" self.leds.power_up() def reset_buffer(self): """Resets current entered passcode""" self.entry_buffer = "" def fsm_signal(self, signal): """Receive signal from FSM""" self.entry_buffer += signal def get_next_signal(self): """Get next signal from Keypad""" return_signal = None if self.override_signal: return_signal = self.override_signal self.override_signal = None else: return_signal = self.keypad.get_next_signal() return return_signal def verify_login(self): """Verify passcode""" print(self.entry_buffer) print(self.read_passcode()) if self.entry_buffer == self.read_passcode(): self.override_signal = "Y" self.twinkle_leds() else: self.override_signal = "N" self.flash_leds() self.entry_buffer = "" def validate_passcode_change(self): """Validate new passcode""" passcodes = self.entry_buffer.split('*') # if not re.search(r"[^\d]", self.passcode[0]): if passcodes[0] == passcodes[1] and len(passcodes[0]) >= 4: self.set_new_passcode(passcodes[0]) else: self.twinkle_leds() self.reset_buffer() def set_new_passcode(self, new_passcode): """Sets new passcode""" with open('passcode.txt', 'w') as pass_file: pass_file.write(new_passcode) self.passcode = new_passcode def read_passcode(self): """Reads passcode from file""" if not self.passcode: with open('passcode.txt') as pass_file: self.passcode = pass_file.readline().strip() return self.passcode def light_one_led(self, led, duration): """Light specific LED""" self.leds.light_single(led, duration) def flash_leds(self): """Flash all LEDs""" self.leds.flash() def twinkle_leds(self): """Twinkle all LEDs""" self.leds.twinkle() def exit_action(self): """Power Down LEDs""" self.leds.power_down()
class KPC: """ Keypad controller coordinates activity between classes and password verification """ __logger = Logger() def __init__(self, override_signal=None, password_file_path="password.txt"): self.current_led = 0 self.duration_buffer = "" self.keypad = Keypad() self.led_board = LEDBoard() self.password_file_path = password_file_path self.override_signal = override_signal self.input_buffer = [] self.previous_input_buffer = [] self.actions = { None: lambda s=None: None, "A1": self.boot, "A2": self.append_password_char, "A3": self.verify_login, "A4": self.boot, "A5": lambda s=None: None, "A6": self.next_entry, "A7": self.next_entry, "A8": self.validate_passcode_change, "A9": self.choose_led, "A10": self.append_duration_digit, "A11": self.apply_led_lighting, "A12": self.show_power_down, } def boot(self, signal=None): """ Display power-up and reset input buffer """ self.led_board.power_up_blink() self.reset_input_buffer() def next_entry(self, signal=None): """ Go to the next input stage """ self.show_success() self.reset_input_buffer() self.__logger.debug("Entering next input stage") def reset_input_buffer(self, signal=None): """ Clear password buffer """ self.previous_input_buffer = self.input_buffer self.input_buffer = [] self.__logger.debug("Cleared input entry") def get_next_signal(self): """ Return override signal if not blank, otherwise query keypad for next pressed key """ if self.override_signal is not None: sig = self.override_signal self.override_signal = None return sig return self.keypad.get_next_signal() def append_password_char(self, signal): """ Append a character to the password under construction """ self.input_buffer.append(signal) self.__logger.debug(f"Appended character: {signal}") def choose_led(self, signal): """ Set the LED ID which is selected for activation """ self.current_led = int(signal) def append_duration_digit(self, signal): """ Append a decimal digit to the duration (in seconds) the LED will be high for """ self.duration_buffer += signal def apply_led_lighting(self, signal=None): """ Apply lighting to the inputted LED for the inputted duration """ if self.duration_buffer != "": self.light_one_led(self.current_led, int(self.duration_buffer)) self.duration_buffer = "" def verify_login(self, signal=None): """ Check that entered password matches the one in the password file """ with open(self.password_file_path, "r") as pass_file: password = pass_file.readline() read_password = "".join(self.input_buffer) self.__logger.debug( f"Password received: {read_password}. Password expected: {password}" ) if password == read_password: self.override_signal = "Y" self.show_success() self.reset_input_buffer() self.__logger.info("Succesfully logged in") else: self.override_signal = "N" self.show_failure() self.reset_input_buffer() self.__logger.info("Failed to log in") def validate_passcode_change(self, signal=None): """ Check that new password is valid """ new_pass = "".join(self.previous_input_buffer) new_pass_confirm = "".join(self.input_buffer) if new_pass.isnumeric() and len(new_pass) >= 4: if new_pass_confirm == new_pass: with open(self.password_file_path, "w") as pass_file: pass_file.write(new_pass) self.show_success() self.__logger.info("Succesfully changed password") self.__logger.debug(f"New password: {new_pass}") else: self.__logger.debug("Passwords didn't match") self.__logger.debug( f"First entry: {new_pass}. Second entry: {new_pass_confirm}" ) self.__logger.info("Failed to change password") else: self.show_failure() self.__logger.debug(f"Malformed password candidate: {new_pass}") self.__logger.info("Failed to change password") self.reset_input_buffer() def light_one_led(self, led_id, led_duration): """ Request that LED #led_id is turned on for led_duration seconds""" self.led_board.light_led(led_id, duration=led_duration) def flash_leds(self): """ Call LED board and request flash all lights """ self.led_board.flash_all_leds(1) def twinkle_leds(self): """ Call LED board and request twinkle all lights """ self.led_board.twinkle_all_leds(1) def exit_action(self): """ Call LED board and request power down light sequence """ self.led_board.power_down_blink() def show_success(self): """ Call LED board and request success sequence """ self.led_board.twinkle_all_leds(0.5) def show_failure(self): """ Call LED board and request failure sequence """ self.led_board.flash_all_leds(0.2) def show_power_down(self, signal=None): """ Call LED board and request power-down sequence """ self.led_board.flash_all_leds(0.1) sleep(0.2) self.led_board.flash_all_leds(0.3) def do_action(self, action, signal): """ Perform submitted action """ self.actions[action](signal)