pythonpython-3.xraspberry-pi-zero

Python password alarm for five minutes


I have written this python program for a game:

print("CC ACTIVATED")
import lcddriver
import time
import subprocess
display = lcddriver.lcd()
try:
    display.lcd_display_string("CC... ", 1) 
    time.sleep(2)
    display.lcd_display_string("ONLINE", 2)
    time.sleep(2)
    display.lcd_clear()
except Exception:
    print("SCREEN ERROR")
try:
    display.lcd_display_string("SETUP A", 1) 
    display.lcd_display_string("PASSWORD? Y/N", 2)
except Exception:
    print("SCREEN ERROR")
activate = input("")
if activate == 'y':
    print("ACTIVATED")
    try:
        display.lcd_clear()
        display.lcd_display_string("", 1) 
        time.sleep(2)
        display.lcd_display_string("LOADING", 2)
        time.sleep(2)
        display.lcd_clear()
    except Exception:
        print("SCREEN ERROR")

else:
    print("ABORT")
    try:
        display.lcd_clear()
        display.lcd_display_string("", 1) 
        time.sleep(2)
        display.lcd_display_string("ABORT", 2)
        time.sleep(2)
        display.lcd_clear()
        subprocess.call(["sudo","halt"])
    except Exception:
        print("SCREEN ERROR")
        subprocess.call(["sudo","halt"])
k = True
while k:
    
    try:
        display.lcd_clear()
        display.lcd_display_string("ENTER PASWORD", 1) 
        display.lcd_display_string("----------------", 2)
    except Exception:
        print("SCREEN ERROR")
    pasword = input("")
    display.lcd_clear()
    try:
        display.lcd_clear()
        display.lcd_display_string("YOU TYPED:", 1) 
        display.lcd_display_string(pasword, 2)
        time.sleep(2)
        display.lcd_display_string("CONFIRM? Y/N", 1) 
    except Exception:
        print("SCREEN ERROR")
    ok = input("")
    if ok == 'y':
        k = False
    else:
        display.lcd_clear()
try:
    display.lcd_clear()
    display.lcd_display_string("PASSWORD", 1) 
    display.lcd_display_string("SET", 2)
except Exception:
    print("SCREEN ERROR")
time.sleep(2)
run = True
try:
    display.lcd_clear()
    display.lcd_display_string("STARTING ", 1) 
    display.lcd_display_string("GAME...", 2)
except Exception:
    print("SCREEN ERROR")
time.sleep(2)
while run:
    try:
        display.lcd_clear()
        display.lcd_display_string("ENTER PASSWORD ", 1) 
        display.lcd_display_string("TO DEACTIVATE", 2)
    except Exception:
        print("SCREEN ERROR")
    pasword1 = input("")
    if pasword1 == pasword:
        try:
            display.lcd_clear()
            display.lcd_display_string("PASSWORD....", 1)
            time.sleep(2)
            display.lcd_display_string("ACCEPTED", 2)
            time.sleep(2)
            display.lcd_clear()
            display.lcd_display_string("DEACTIVATED", 2)
            subprocess.call(["sudo","halt"])
            time.sleep(10)
        except Exception:
            print("SCREEN ERROR")
            subprocess.call(["sudo","halt"])
    else:
        try:
            display.lcd_clear()
            display.lcd_display_string("PASSWORD....", 1)
            time.sleep(2)
            display.lcd_display_string("UNACCEPTED", 2)
            time.sleep(2)
        except Exception:
            print("SCREEN ERROR")

It runs on a raspberry pi and works absolutely fine, but there is one thing I want to do that is a bit above my skill level. I need this program to give you three attempts to guess the password,then at the fourth attempt play an audio recording. Afterward it needs to respond to failed attempts with the audio recording for five minutes and then go back to the silent three chances. I know how to get it to do the audio recording, but I need help with the five minute part. Does anyone here know how to do this? Thanks.


Solution

  • To permit three password attempts, you will need a counter variable which will count up to three with each failed attempt.

    Rather than just running while k == True, you want to check against both k == True and attempts <= 3. As far as waiting five minutes, you will want to create a timestamp of when the user last guessed.

    from datetime import datetime
    
    ...
    k = True
    password_attempts = 0
    
    while k and password_attempts < 4:
        try:
            display.lcd_clear()
            display.lcd_display_string("ENTER PASWORD", 1)
            display.lcd_display_string("----------------", 2)
        except Exception:
            print("SCREEN ERROR")
        pasword = input("")
        display.lcd_clear()
        try:
            display.lcd_clear()
            display.lcd_display_string("YOU TYPED:", 1)
            display.lcd_display_string(pasword, 2)
            time.sleep(2)
            display.lcd_display_string("CONFIRM? Y/N", 1)
        except Exception:
            print("SCREEN ERROR")
        ok = input("")
        if ok == "y":
            k = False
        else:
            display.lcd_clear()
            password_attempts += 1
            if password_attempts == 4:
                #Create a timestamp of last attempt
                last_request = datetime.now()
                current_request = datetime.now()
                while((last_request - current_request).total_seconds() < 5 * 60):
                    #Code to play music
                    current_request = datetime.now()
    

    Then it's up to you to re-route the player back to the point in the program where they try entering the passwords again.

    But, the design choices you've made at the beginning of this project will really start to get in the way of what you want to do.

    I suggest you consider a redesign of your program, in order to make working on it much easier and more pleasant.

    One of the best parts of programming is code re-use; this is most easily understood with functions. In Python, you create a function with the syntax def function_name():

    Then, when you want to run the code within that function, you simply call it by name: function_name().

    What does this mean for your app?

    You could wrap writing to the LCD in a method, so that you can avoid repeatedly typing out the same try:... except: block (by the way... when you write except Exception, you are catching ALL exceptions your program might throw. This is considered bad practice, because you may not want to do the same thing irrespective of what the exception was in the first place. Rather, try to find a specific exception you're trying to catch, and catch that one by name, specifically).

    An example of rewriting the LCD printing:

    def print_to_lcd(statements_to_print: [str]):
        line_number = 1
        try:
            for statement in statements_to_print:
                display.lcd_display_string(statement, line_number)
                line_number += 1
        except Exception:
            print("SCREEN ERROR")
    

    Then, you just produce a list of things for the LCD to print, and call the LCD function with them:

    things_to_write = ["PASSWORD...", "UNACCEPTED"]
    print_to_lcd(things_to_write)
    

    The same can be said about how you check your password value, when you play the music, etc.

    Any time you find yourself repeatedly re-writing the same information, take a moment and think if there's a way you can write it once, and just re-use it. It'll make your programs much easier to write, and much easier to use.

    Particularly in this case, since you want to re-do the same thing after waiting for a period of time. Imagine, rather than having to write tons of if-statements, when the user enters the password wrong for the fourth time, you just write something like:

    play_music_for_five_minutes()
    prompt_for_password()
    

    Let me know if there are any further questions I can answer!