Raspberry Pi と交通系ICカードを使ったポイントシステム(ソフトウェア編)

ポイントシステムをつくる

概要図はこんな感じ。 f:id:u9bo:20160626215531p:plain raspi+カードリーダでIDを読み取り、ID情報をサーバへ送信して集計します。 raspiはクライアントとして利用します。そうすることで、今後のraspi増設にも対応できそうです。

もろもろ開発

まずは、nfcpyをpathの通っている場所へ移動します。

$ sudo mv /root/nfcpy /usr/local/lib/nfcpy

こんなプログラムnfctest.pyを作成します。 ライブラリにpygameurllib2を使用しています。 Python初心者なのでもっと良い書き方あるかも。

import binascii
import nfc
import urllib
import urllib2
from urllib2 import Request, urlopen, URLError
from pygame import mixer


class MyCardReader(object):
    def __init__(self):
        mixer.init()
        self.alert = mixer.Sound('./beep.wav')
    
    def on_connect(self, tag):
        print "touched"
        self.idm = binascii.hexlify(tag.idm)
        return True

    def read_id(self):
        clf = nfc.ContactlessFrontend('usb')
        try:
            clf.connect(rdwr={'on-connect': self.on_connect})
        finally:
            clf.close()

    def put_http(self):
        url = 'http://hogehoge.com/nfc.php'
        values = {'id':self.idm}
        data = urllib.urlencode(values)
        req = urllib2.Request(url,data)
        try:
            response = urllib2.urlopen(req)
            self.httpres = response.read()
        except URLError, e:
            if hasattr(e, 'reason'):
                print 'We failed to reach a server.'
                print 'Reason: ', e.reason
            elif hasattr(e, 'code'):
                print 'The server couldn\'t fulfill the request.'
                print 'Error code: ', e.code
        else:
           print self.httpres

    def playsound(self):
        self.alert.play()

if __name__ == '__main__':
    cr = MyCardReader()
    while True:
        print "touch card:"
        cr.read_id()
        print "released"
        print cr.idm
        cr.put_http()
        cr.playsound()

プログラムの概要を説明すると、

  1. ICカード読み込み
  2. カードIDを集計サーバのhttp://hogehoge.com/nfc.phpへ送信

  3. 情報を送信したら./beep.wavを再生

といった感じです。 平文でIDを送信するのはなんだか怖いので、本格的に利用する場合は暗号化など考慮する必要がありそうです。

集計サーバのhttp://hogehoge.com/nfc.phpはこんな感じ。

<?php
$id = $_POST['id'];
if (!empty($id)) {
    date_default_timezone_set('Asia/Tokyo');
    $fp = fopen("./nfclog.txt", "a");
    $str = date('Y-m-d H:i:s')."\t".$id."\n";
    echo $str;
    fwrite($fp, $str);
    fclose($fp);
} else {
    echo "id未指定¥n";
}

$_POST['id']./nfclog.txtに記録しているだけです。 本格的に使う場合は、DBへ登録するようにしたらよいですね。

動かしてみた

うごかしてみました。

$ sudo python nfctest.py 
touch card:
touched
released
xxxxxxxxxxxxxx
2016-06-26 18:25:40 xxxxxxxxxxxxxx

こんな感じで、

  • 読み取ったID
  • サーバのレスポンス(タイムスタンプとID)

が表示されます。

今後の予定

  • プログラムnfctest.pyのデーモン化
  • 集計システムの開発

qiita.com

blog.shibayan.jp