怠惰になるために本気出す

電子工作で色々作ってます

Sesame解錠編④ エラー時にブザーを鳴らす

ラズパイの本体には剣山のようなものがありますが、当たり前ですが花を生けるものではありません。
GPIOピンと言ってデジタル信号の入出力用のものです。電子工作をしていくうえでLチカ(LEDをチカチカさせること)をやる言わば電子工作の登竜門のような作業です。

Lチカに関する記事は腐るほどあるので出力の確認作業のみ行います。
ブザーを鳴らすタイミングは2通りで、
①登録してあるICカード以外のものがタッチされたときピッと0.5秒鳴らす
②何らかの影響でネットワークにエラーが発生してレスポンスが200以外のものが返ってきたときにピッピッピッ(0.5秒ONを3サイクル)と鳴らす
の二通りにしました。 毎回解錠処理の度にブザーが鳴ると鬱陶しそうな気がしたので何か不具合があったときだけにしました。

import datetime, base64, requests, json, binascii, nfc, os, time
import RPi.GPIO as GPIO
from threading import Thread, Timer
from Crypto.Hash import CMAC
from Crypto.Cipher import AES

            
idm1 = b"お手持ちのICカード1" 
idm2 = b"お手持ちのICカード2"

pin = 40 #GPIOのピン指定

#ICカード待受の1サイクル秒
TIME_cycle = 1.0
#ICカード待受の反応インターバル秒
TIME_interval = 0.2
#タッチされてから次を開始するまでの無効化する秒
TIME_wait = 3

#NFC接続リクエストのための準備
#212F(Felica)で設定
target_req_ic = nfc.clf.RemoteTarget("212F")
#0003(IC cart)
target_req_ic.sensf_req = bytearray.fromhex("0000030000")

print('ICカードをタッチしてください...')

while True:
    
    #USB接続されたカードリーダーをインスタンス化
    clf = nfc.ContactlessFrontend('usb')
    #ICカード待受開始
    target_res = clf.sense(target_req_ic, iterations=int(TIME_cycle//TIME_interval)+1, interval=TIME_interval)
    
    if not target_res is None:
        tag = nfc.tag.activate_tt3(clf, target_res)
        tag.sys = 3
        
        #IDmを取り出す
        idm = binascii.hexlify(tag.idm)
        print(idm)
        
        #特定のIDmだった場合のアクション
        if idm == idm1 or idm == idm2:
            uuid = '個人のUUID'
            secret_key = '個人のシークレットキー'
            api_key = '個人のAPIキー'

            # HTTP header
            headers = { 'x-api-key': api_key }

            # signの生成
            cmac = CMAC.new(bytes.fromhex(secret_key), ciphermod=AES)
            message = int(datetime.datetime.now().timestamp()).to_bytes(4, 'little', signed=False)[1:4]
            cmac.update(message)
            sign = cmac.hexdigest()
            
            print("【 特定のIDmにより施解錠 】")
            #鍵の状態取得
            surl = f'https://app.candyhouse.co/api/sesame2/{uuid}'
            sres = requests.get(surl, headers=headers) #リクエスト
            print(sres.text)
            
            if "unlocked" in sres.text:
                print("close")
                cmd = 82
                history = 'close (Web API)'

            else:
                print("open")
                cmd = 83
                history = 'open (Web API)'
            history = base64.b64encode(history.encode()).decode() #履歴に「open」or「close」を記載
            url = f'https://app.candyhouse.co/api/sesame2/{uuid}/cmd'
            body = {
                'cmd': cmd,
                'history': history,
                'sign': sign
            }
            res = requests.post(url, json.dumps(body), headers=headers)
            print(res.status_code, res.text)
            str_res = str(res.status_code)
            #ネットワークでエラーが発生して200が返ってこない場合の処理
            if not "200" in str_res:
                print("NG")
                #GPIOピン設定
                GPIO.setmode(GPIO.BOARD)
                GPIO.setup(pin,GPIO.OUT)
                GPIO.output(pin, 1)
                time.sleep(0.5)
                GPIO.output(pin, 0)
                time.sleep(0.5)
                GPIO.output(pin, 1)
                time.sleep(0.5)
                GPIO.output(pin, 0)
                time.sleep(0.5)
                GPIO.output(pin, 1)
                time.sleep(0.5)
                GPIO.output(pin, 0)
                time.sleep(0.5)                
                GPIO.cleanup()               
            time.sleep(TIME_wait)
            
        else:
            print("カードが違います")
            #GPIOピン設定
            GPIO.setmode(GPIO.BOARD)
            GPIO.setup(pin, GPIO.OUT)
            GPIO.output(pin, 1)
            time.sleep(0.5)
            GPIO.output(pin, 0)
            GPIO.cleanup()
            time.sleep(TIME_wait)
            
    clf.close()
#end while


記事にしながらプログラムを見返していたんですなんとも見にくい書き方してますね。
正常に動くし見栄えが悪いだけなので特に書き直す予定はありませんが。

完成したプログラムから必要なところを抜粋しながら書いているのでもしかしたら抜けてるところがあってうまく動かないかもしれません。
その際はご指摘いただければと思います。