この記事は"QRコードを使った入場システムを自作する"シリーズの記事です。
#前回
"[1]独自のフォーマットに基づいてQRコードを発行する"では独自のフォーマットのQRコードを発行してデータベースに登録することができました。
今回はデータベースに登録したQRコードの読み取り方です。
#QRコードを読み取るには
スキャナーを用意する予算がなかったのiOSアプリのPythonista3を利用してQRコードを読み取ります。
##手順
Pythonista3を利用しなくてもなんでも読み取った後の処理は同じです。
- QRコードをスキャン
- 読み取ったコードを文字列に変換
- MySQLで検索をかける
##Pythonista3でQRコードを読み取る方法
今回一番きつかったのがこの部分で、objective-cをPython上で動かさなければいけませんでした。
Pythonistaには標準でobjc_utilというモジュールが入っているのでそれを利用します。
###とは言っても...
objective-cなんか生まれてから一度も利用したことがなくswiftが主流?になってきているので今回はこちらを流用させていただいた。(一部改変)
###ということで
以下がソースコードになる。
# Barcode scanner demo for Pythonista
from objc_util import *
from ctypes import c_void_p
import mysql.connector as testdb
import ui
import sound
found_codes = set()
main_view = None
AVCaptureSession = ObjCClass('AVCaptureSession')
AVCaptureDevice = ObjCClass('AVCaptureDevice')
AVCaptureDeviceInput = ObjCClass('AVCaptureDeviceInput')
AVCaptureMetadataOutput = ObjCClass('AVCaptureMetadataOutput')
AVCaptureVideoPreviewLayer = ObjCClass('AVCaptureVideoPreviewLayer')
dispatch_get_current_queue = c.dispatch_get_current_queue
dispatch_get_current_queue.restype = c_void_p
#QRコードの読み取り
def captureOutput_didOutputMetadataObjects_fromConnection_(_self, _cmd, _output, _metadata_objects, _conn):
objects = ObjCInstance(_metadata_objects)
for obj in objects:
s = str(obj.stringValue())
if s not in found_codes:
found_codes.add(s)
#読み取り終了後にWindowを閉じる。
main_view.close()
MetadataDelegate = create_objc_class('MetadataDelegate', methods=[captureOutput_didOutputMetadataObjects_fromConnection_], protocols=['AVCaptureMetadataOutputObjectsDelegate'])
@on_main_thread
def main():
global main_view
delegate = MetadataDelegate.new()
main_view = ui.View(frame=(0, 0, 400, 400))
main_view.name = 'Barcode Scanner'
session = AVCaptureSession.alloc().init()
device = AVCaptureDevice.defaultDeviceWithMediaType_('vide')
_input = AVCaptureDeviceInput.deviceInputWithDevice_error_(device, None)
if _input:
session.addInput_(_input)
else:
print('Failed to create input')
return
output = AVCaptureMetadataOutput.alloc().init()
queue = ObjCInstance(dispatch_get_current_queue())
output.setMetadataObjectsDelegate_queue_(delegate, queue)
session.addOutput_(output)
output.setMetadataObjectTypes_(output.availableMetadataObjectTypes())
prev_layer = AVCaptureVideoPreviewLayer.layerWithSession_(session)
prev_layer.frame = ObjCInstance(main_view).bounds()
prev_layer.setVideoGravity_('AVLayerVideoGravityResizeAspectFill')
ObjCInstance(main_view).layer().addSublayer_(prev_layer)
session.startRunning()
main_view.present('sheet')
main_view.wait_modal()
session.stopRunning()
delegate.release()
session.release()
output.release()
#QRコードを読み取った際の処理
if found_codes:
#cur = conn.cursor()
scan_code = str(''.join(found_codes))
#table: QRidのデータを照合
table = 'QRid'
cur.execute("select * from QRid where QR=%s",(scan_code,))
result = cur.fetchall()
if len(result) == 0:
sound.play_effect('digital:PhaserUp4')
print('該当するデータがありません。')
vibrate([50,0,50,0,50,0,50])
else:
sound.play_effect('arcade:Coin_5')
print('ID'+'{:>15}'.format('DATE')+'{:>11}'.format('TIME'))
for i in result:
print(*i)
if __name__ == '__main__':
#MySQLへ接続
conn = testdb.connect(
user = 'test',
password = '12345',
host = '192.168.x.x',
port = '3306',
database='QRtest'
)
#接続ステータスを確認
conn.ping(reconnect=True)
print('[Status] ', end='')
print(conn.is_connected())
cur = conn.cursor()
main()
#MySQLへの接続を終了
cur.close()
conn.commit()
conn.close()
スクリプトを走らせるとカメラウィンドウが表示されます。
正常に読み取られるとこのウィンドウが閉じてコンソールが開きます。
MySQL上に登録されている情報が表示されれば成功です。
#次回予告
[2-2]作成したQRコードを読み取り識別する。でよりわかりやすいGUIを追加します。読み取り機は次回で完成です。