Build management system with Raspberry pi and QR Part2

#JA

はじめに

前回の続き。
カメラでのQR読み込みは完了したので、次はこれといった操作がなければ自動ログアウトできる機能を、実装していきます。

ログイン/ログアウト

まずログイン時にログインユーザーの名前を記載した、login_userというファイルを生成することにします。
ログアウト時は、login_userというファイルを削除します。
また今回は、後ほどブラウザ上で貸出返却の状態を確認したり、デバイスの追加削除などをできるようにするため、 adminというファイルを管理者がログインした際に作成します。

def login_user(user_name):
    if user_name == "admin":
        f = open('admin', 'w')
        f.write(user_name)
        f.close()
    f = open('login_user', 'w')
    f.write(user_name)
    f.close()

def logout_user(user_name):
    if user_name == "admin":
        os.remove('admin')
    os.remove('login_user')

自動ログアウトのためのタイマー実装

さて、カードキーをかざして使用するコピー機を使ったことがある方は想像できるかもしれませんが、 特に動作がなかった時、ある一定時間経つと自動でログアウトします。
今回は、下記のようにログイン時にloggerというファイルを作成しておき、タイマーを設定します。
タイマーはログイン時のみ60秒間をセットします。

# auto_logout
if os.path.exists('login_user'):
    if not os.path.exists('logger'):
        f = open('logger', 'w')
        f.write(str(pyautogui.position()))
        f.close()
        stop = False
        auto_log(60)

そして、60秒間操作がなかった場合、timeupというファイルを作成します。

def timer_log(secs):
    i = secs
    while not stop:
        if i == 0:
            break
        print(i)
        i -= 1
        time.sleep(1)
    if not stop:
        f = open('timeup', 'w')
        f.write('timeup')
        f.close()

def auto_log(target_time):
    thread = Thread(target=timer_log,args=(target_time,))
    thread.start()

つまり、loggerは自動ログアウトするかの判定ファイル、timeupはタイマーのカウントが終了したことを示すファイルとしました。
実装の仕方としては、前回のロックアンロックと同じ、threadを使用して、タイマーを実装しました。

自動ログアウト回避の条件と実装

次に、自動ログアウト回避の条件として、下記を設定しました。

貸出返却操作があった
マウスが動いた

「貸出返却操作があった」は、QRコードでデバイスのIDが読み込まれたときに先ほどのloggerファイルに貸出(borrow)もしくは返却(return)の文字を記載します。

def modify_log(msg):
    f = open('logger', 'w')
    f.write(msg)
    f.close()

「マウスが動いた」は、ログイン時のところで実装したようにpyautoguiのライブラリを使用して、マウスカーソルの現在位置を取得、記録します。

$ pip3 install pyautogui
if not os.path.exists('logger'):
    f = open('logger', 'w')
    f.write(str(pyautogui.position()))
    f.close()

そしてタイマーでカウントしている間にマウスカーソルが動くと、タイムアップ後に、下記compare_log()で自動でログアウトするか否かを判定します。

def compare_log():
    cpos = str(pyautogui.position())
    f = open('logger', 'r')
    for line in f:
        if(line == cpos):
            f.close()
            return True
    f.close()
    return False

もし、自動でログアウトできないと判断された場合は、再度タイマーを設定します。このときの時間は10秒です。

if os.path.exists('timeup'):
    if compare_log():
        print("auto logout is done")
        delf()
        print("Good Bye! {0}!!".format(username))
        logout_user(username)
        userid = 0
        username = ""
        lf = 0
    else:
        print("interrupt auto logout")
        os.remove('timeup')
        f = open('logger', 'w')
        f.write(str(pyautogui.position()))
        f.close()
        stop = False
        auto_log(10)

タイマーカウント中のログアウト

さて、今回実装で一番悩んだのは、タイマーカウント中にログインIDをかざしてログアウトした場合、タイマーをリセットする必要があるけれど、どう実装するか。
今回はthreadでタイマーを実装しているので、実行されているthreadを止める方法をググったところ、どうやらboolで止めればよいらしい。
下記を参考にstopというbool変数で制御しました。

参考URL : https://qiita.com/tag1216/items/2dcb112f8018eb19a999

def timer_log(secs):
    i = secs
    while not stop:
        if i == 0:
            break
        print(i)
        i -= 1
        time.sleep(1)
    if not stop:
        f = open('timeup', 'w')
        f.write('timeup')
        f.close()

これにより、カウント中もログアウトが実行されれば、stopをTrueにし、関連ファイルを削除することで次の人がスムーズに使うことができます。

print("Good Bye! {0}!!".format(username))
logout_user(username)
stop = True
delf()
userid = 0
username = ""
lf = 0
lock_unlock()

動作テスト

最初にziroのユーザーIDをかざした後、60秒のカウントがはじまります。
その後、デバイスを借り、再度ziroのユーザーIDをかざしてマニュアルログアウトしてます。

qr5

今度はichiroでログインし直し、デバイスを借ります。
借りたことで自動ログアウトが阻止され(interrupt auto logout)、10秒のタイマーのカウントがはじまり自動ログアウトしてます。

qr6

動画は貼れませんでしたが、うまく機能しているようです。

コード

ここまでのコードは下記にあげてます。ご参考ください。

Github : https://github.com/RuBisCO28/QR_Reader

最後に一言

threadは便利な反面、奥が深そうです。 次回はブラウザで貸出状況を確認できる機能を、実装していく予定です。