シェルスクリプトマガジン

香川大学SLPからお届け!(Vol.71掲載)

著者:樋口史弥

COVID-19の流行により、香川大学でもサークル活動に制限がかかっています。そこで、ICカードと非接触ICカードリーダーを用いて、部室の入退室をモニタリングするシステムを作成しました。部室の利用状況をリアルタイムに確認できれば密を避ける目安になりますし、何かあったときのための記録としても有用です。

シェルスクリプトマガジン Vol.71は以下のリンク先でご購入できます。

図6 IDmを読み取って表示するPythonコード

import nfc
import binascii

def on_connect(tag):
  data={'idm': binascii.hexlify(tag.idm).decode('utf-8')}
  print(data)
  return True

def main():
  with nfc.ContactlessFrontend('usb:ベンダーID:プロダクトID') as clf:
    while clf.connect(rdwr={'targets': ['212F'],
                            'on-connect': on_connect}):
      pass

if __name__ == "__main__":
  main()

図7 サーバーと連携させるために挿入するPythonコード

import json
from os import getenv
import urllib.request

def post_data(data):
  headers = { 'Content-Type': 'application/json', }
  req = urllib.request.Request(getenv('REQUEST_URI'),
                               data=json.dumps(data).encode('utf-8'),
                               headers=headers, method='POST')
  try:
    with urllib.request.urlopen(req) as res:
      if res.code == 200:
        result = json.loads(res.read().decode('utf-8'))['result']
        if result == 'in':
          print('IN')
        else:
          print('OUT')
  except urllib.error.HTTPError as err:
    print("err: ", err.read())

図12 退出かどうかを調べるSQL 文

$sql = 'SELECT * '.
        'FROM log INNER JOIN user '.
        'ON log.user_id=user.id '.
        'WHERE exit_time IS NULL '.
        'AND enter_time >= DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 1 DAY) '.
        'AND user.idm=? '.
        'ORDER BY log.enter_time DESC LIMIT 1';

図13 入室情報を表示するコード(index.js)により追加される情報の例

<div class="use_now">
  <div>
    <div class="time">2021-03-12 12:54:31</div>
    <div class="name">guest</div>
  </div>
  <div>
    <div class="time">2021-03-12 12:42:27</div>
    <div class="name">user1</div>
  </div>
</div>

図15 音を鳴らすために挿入するPythonコード

from gpiozero import TonalBuzzer
from gpiozero.tones import Tone
from time import sleep

def beep(hertz):
  bz = TonalBuzzer(4)
  bz.play(Tone(frequency=hertz))
  sleep(0.2)
  bz.stop()