obnizでRFIDタグを使ってユーザー名とID認証やってみた

# アドベントカレンダーに参加
はいどうも。
今回はobnizアドベントカレンダーに参加しました。
### アドベントカレンダーとは
12/1~25のクリスマスまでの期間に日数を数えるために使用されるカレンダー。
同時期に特定のテーマに沿って毎日ブログなどに記事を投稿していく企画もアドベントカレンダーと呼ばれています。
ヨーロッパなどで合わせて開催されるクリスマスマーケットも良い雰囲気で好きです。

というわけでした。じゃあまたね！
流石にダメか。

# RFIDタグとは
一週間前くらいにリリースされた最新のobniz.js 2.5.0でRFIDタグのパーツライブラリが実装されました！
[Obniz公式ドキュメント：MFRC522](https://github.com/obniz/obniz/tree/master/src/parts/Wireless/MFRC522)
RFIDタグとは、PASMOやSUICAのような非接触ICカードと同様に、アンテナにかざすと非接触でカードに読み書きできるカードやキーホルダーの形をしているものです。

個人的には「非接触」とかスマートな感じがして好きですね。
MFRC522なら全部で値段が300円くらいなのも嬉しいところ。
あと、ポイントカードとか学生証などがRFIDタグだった場合、データの読み書きは出来ませんがカードのIDが読み取れるので、識別が出来るのめっちゃ面白い。
自分でもやってみて何枚か読めました。
ただセキュリティホールがあって、カード偽造の手段があるのでかなりセキュリティが求められるところには使えないですね。また、電波法にギリ引っかかってないはずですが、電波強度的に屋外で使う際は自己責任で。

![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246335/761b7d5a-022d-1056-4622-9deb27c6396d.jpeg)
(左：アンテナ、右：カード・キーホルダー型のRFIDタグ)

# 配線図
![Screenshot from 2019-11-30 18-32-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246335/cd402d4e-4fac-4ed2-403a-eb96777c67db.png)




# ユーザー名書き込み
[Obniz公式ドキュメント：MFRC522](https://github.com/obniz/obniz/tree/master/src/parts/Wireless/MFRC522)より、
”MFRC522はuidとPICC Typeのほかに書取，読取の出来るデータ列を用意しています．
その構成は以下のようになっています．”

| Sector (= 4Block) | Block (= 16Byte) |
|:--|:--|
| 0 | 0(UID), 1, 2, 3(Reserved) |
| 1 | 4, 5, 6, 7(Reserved) |
| 2 | 8, 9, 10, 11(Reserved) |
| 3 | 12, 13, 14, 15(Reserved) |
| ... | ... |
| 15 | 60, 61, 62, 63(Reserved) |

とのことなので、今回は5Block目にユーザー名を書き込んでいこうかと思います。
1Block当たり16Byteなので、Byte→Char変換で16文字は書き込めますね。

###プログラム
早速プログラム。
長い印象を受けますが、大体obniz公式ドキュメントのコピペです。

obniz公式ドキュメントではバイト列の書き込みしかやってないのでUTF16への変換だけ書きました。
まあいうてJSの関数使うだけ。ほんとJSって簡単ですね...C辛い

5Block目に"k_zoo"と書き込みました。
また、読み取ったときの見やすさ的に16バイトの残りの部分を[space]で埋めてます。

alert関数はブザーを鳴らしてます。
やっぱりカードかざした時に”ピピッ”ってなって欲しくないですか？俺は欲しい。

```html:write_user.html
<html>

<head>
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
	<script src="https://unpkg.com/obniz@2.5.0/obniz.js"></script>
</head>

<body>
	<div id="obniz-debug"></div>
	<script>
		var obniz = new Obniz("　"); 	// obniz ID here
		obniz.onconnect = async function () {	// If obniz connect
            var mfrc522 = obniz.wired("MFRC522", { cs: 0, clk: 1, mosi: 2, miso: 3, gnd: 4, rst: 5, vcc: 6 });

			console.log("Please put chip or keycard in the antenna inductive zone!");
            whileFlag = 1;
            while (whileFlag) {	// Loop until finishing to read all data
				try {
                    // Detect card
                    let card = await mfrc522.findCardWait();
                    console.log("Card is detected!");
                    console.log("UID		: " + card.uid);
                    console.log("PICC Type 	: " + card.PICC_Type);
                    
                    alert(7);   // alert
                    
                    let Block = 5;
                    // Read block data from card
                    response = await mfrc522.readBlockDataWait(Block, card.uid);
                    console.log("Block: " + Block + " Data: " + buffer_to_string(response));

                    // Write block data to card
                    let buffer = string_to_buffer("k_zoo");
                    var len = 16 - buffer.length;
                    for (var i = 0; i < len; i++)
                        buffer.push(32);    // push [space]
                    console.log("Writing data to Block " + Block + "...");
                    await mfrc522.writeBlockDataWait(Block, buffer);
                    console.log("Wrinting finished.");

                    // Finish while()
                    whileFlag = 0;
                }
                catch(e) {  // Not Found or Error
                    console.error(e);
                }
			}
		}

		async function alert(buzzer) {	// Alert buzzer
			if (buzzer === undefined)
				throw "alert_ERROR";
			// default settings
			let frequency = 2800;
			let count = 2;
			let time = 70;
			let duty = 20;
			// generate PWM
			var pwm = obniz.getFreePwm();
			for (let i = 0; i < count; i++) {
				await this.obniz.wait(time);
				pwm.start({ io: buzzer });
				pwm.freq(frequency);
				pwm.duty(duty);
				await this.obniz.wait(time);
				pwm.end();
			}
        };
        
        function string_to_buffer(src) {
            return ([].map.call(src, function (c) {
                return c.charCodeAt(0)
            }));
        }
	</script>
</body>

</html>
```

# ユーザー名読み取り、ID認証
カードにはそれぞれ固有のIDがあるので、カードからIDを読み取って、欲しいIDと同じならユーザー名をobnizの液晶に表示します。

```html:read_user_ID.html
<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
    <script src="https://unpkg.com/obniz@2.5.0/obniz.js"></script>
</head>

<body>
    <div id="obniz-debug"></div>
    <script>
        var obniz = new Obniz("　"); 	// obniz ID here
        obniz.onconnect = async function () {	// If obniz connect
            var mfrc522 = obniz.wired("MFRC522", { cs: 0, clk: 1, mosi: 2, miso: 3, gnd: 4, rst: 5, vcc: 6 });
            whileFlag = 1;
            while (whileFlag) {
                try {
                    // Detect card
                    let card = await mfrc522.findCardWait();
                    console.log("Card is detected!");
                    console.log("UID		: " + card.uid);
                    console.log("PICC Type 	: " + card.PICC_Type);

                    alert(7);   // alert

                    let Block = 5;
                    // Read block data from card
                    response = await mfrc522.readBlockDataWait(Block, card.uid);
                    console.log("Block: " + Block + " Data: " + buffer_to_string(response));

                    obniz.display.clear();
                    obniz.display.font(12);
                    if(JSON.stringify(card.uid) === JSON.stringify([105, 49, 186, 85, 183])){
                        obniz.display.print("こんにちは、");
                        obniz.display.print(buffer_to_string(response));
                        whileFlag=0;
                    }else{
                        obniz.display.print("未登録IDです。");
                    }
                } catch (e) {
                    // Not Found or Error
                    console.error(e)
                }

                async function alert(buzzer) {	// Alert buzzer
                    if (buzzer === undefined)
                        throw "alert_ERROR";
                    // default settings
                    let frequency = 2800;
                    let count = 2;
                    let time = 70;
                    let duty = 20;
                    // generate PWM
                    var pwm = obniz.getFreePwm();
                    for (let i = 0; i < count; i++) {
                        await this.obniz.wait(time);
                        pwm.start({ io: buzzer });
                        pwm.freq(frequency);
                        pwm.duty(duty);
                        await this.obniz.wait(time);
                        pwm.end();
                    }
                };

                function buffer_to_string(buf) {
                    return String.fromCharCode.apply("", buf);
                }
            }
        }
	</script>
</body>

</html>
```

## 結果
カードのIDに応じてちゃんとユーザー名を読み取っています。
これを使えば、色んな情報を読み書きできるし、IDなどはサーバーに保存して照合すればデータ管理が別個に出来て面白くなりそうですね。
<img width="300" alt="IMG_20191130_174436.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246335/131895b2-9050-351c-65c4-811b744b72f6.jpeg">
<img width="300" alt="IMG_20191130_174607.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246335/057435e2-1b68-46a0-7b50-15e561b4410e.jpeg">

# 終わりに
やっぱ非接触タグは普通のパーツとはまた違った面白さがありますね。
obnizアドベントカレンダー、スタートしたばかりなので他の人の投稿が楽しみです。

最近Ubuntuに居住するようになりましたが大変便利！もうWindowsには帰りたくない....
Linuxに慣れる一環でRaspiでサーバーもたてたので、その話もおいおい書きたい。
ではまた！

あ、あと宣伝。
obnizではエンジニアとマーケティング/広報担当者を募集しています！
blog.obniz.io/ja/careers/
＜エンジニア＞
自由度の高い環境でIoTを学びながら成長できます！
ものづくりに興味のある方はお気軽にご連絡ください。
＜マーケティング/広報＞
企画を立ち上げたり広告を出して効果を検証するなど、マーケターとしてのお仕事が可能です。
資金力があり自由度の高いスタートアップだからこその経験がしたい方、ご応募お待ちしています！